diff --git a/CHANGES.txt b/CHANGES.txt index 11604de202..df1fb76687 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,7 @@ * Add guardrail for ALTER TABLE ADD / DROP / REMOVE column operations (CASSANDRA-17495) * Rename DisableFlag class to EnableFlag on guardrails (CASSANDRA-17544) Merged from 4.1: + * Handle config parameters upper bound on startup; Fix auto_snapshot_ttl and paxos_purge_grace_period min unit validations (CASSANDRA-17571) * Fix leak of non-standard Java types in our Exceptions as clients using JMX are unable to handle them. Remove useless validation that leads to unnecessary additional read of cassandra.yaml on startup (CASSANDRA-17638) * Fix repair_request_timeout_in_ms and remove paxos_auto_repair_threshold_mb (CASSANDRA-17557) diff --git a/NEWS.txt b/NEWS.txt index 4d9b9f70b3..e44b0e4fe8 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -183,6 +183,9 @@ New features Upgrading --------- + - Parameters of type data storage, duration and data rate cannot be set to Long.MAX_VALUE (former parameters of long type) + and Integer.MAX_VALUE (former parameters of int type). Those numbers are used during conversion between units to prevent + an overflow from happening. (CASSANDRA-17571) - We added new JMX methods `setStreamThroughputMbitPerSec`, `getStreamThroughputMbitPerSec`, `setInterDCStreamThroughputMbitPerSec`, `getInterDCStreamThroughputMbitPerSec` to the JMX MBean `org.apache.cassandra.db:type=StorageService`. They replace the now deprecated methods `setStreamThroughputMbPerSec`, `getStreamThroughputMbPerSec`, `setInterDCStreamThroughputMbPerSec`, and diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml index 6932a5fbcf..d11e5e64bd 100644 --- a/conf/cassandra.yaml +++ b/conf/cassandra.yaml @@ -61,6 +61,7 @@ hinted_handoff_enabled: true # this defines the maximum amount of time a dead host will have hints # generated. After it has been dead this long, new hints for it will not be # created until it has been seen alive and gone down again. +# Min unit: ms max_hint_window: 3h # Maximum throttle in KBs per second, per delivery thread. This will be @@ -68,6 +69,7 @@ max_hint_window: 3h # are two nodes in the cluster, each delivery thread will use the maximum # rate; if there are three, each will throttle to half of the maximum, # since we expect two nodes to be delivering hints simultaneously.) +# Min unit: KiB hinted_handoff_throttle: 1024KiB # Number of threads with which to deliver hints; @@ -81,9 +83,11 @@ max_hints_delivery_threads: 2 # How often hints should be flushed from the internal buffers to disk. # Will *not* trigger fsync. +# Min unit: ms hints_flush_period: 10000ms # Maximum size for a single hints file, in megabytes. +# Min unit: MiB max_hints_file_size: 128MiB # The file size limit to store hints for an unreachable host, in mebibytes. @@ -119,6 +123,7 @@ auto_hints_cleanup_enabled: false # Maximum throttle in KBs per second, total. This will be # reduced proportionally to the number of nodes in the cluster. +# Min unit: KiB batchlog_replay_throttle: 1024KiB # Authentication backend, implementing IAuthenticator; used to identify users @@ -177,6 +182,7 @@ network_authorizer: AllowAllNetworkAuthorizer # Will be disabled automatically for AllowAllAuthenticator. # For a long-running cache using roles_cache_active_update, consider # setting to something longer such as a daily validation: 86400000 +# Min unit: ms roles_validity: 2000ms # Refresh interval for roles cache (if enabled). @@ -188,6 +194,7 @@ roles_validity: 2000ms # using roles_cache_active_update. # Defaults to the same value as roles_validity. # For a long-running cache, consider setting this to 60000 (1 hour) etc. +# Min unit: ms # roles_update_interval: 2000ms # If true, cache contents are actively updated by a background task at the @@ -201,7 +208,8 @@ roles_validity: 2000ms # one example). Defaults to 2000, set to 0 to disable. # Will be disabled automatically for AllowAllAuthorizer. # For a long-running cache using permissions_cache_active_update, consider -# setting to something longer such as a daily validation: 86400000 +# setting to something longer such as a daily validation: 86400000ms +# Min unit: ms permissions_validity: 2000ms # Refresh interval for permissions cache (if enabled). @@ -213,6 +221,7 @@ permissions_validity: 2000ms # using permissions_cache_active_update. # Defaults to the same value as permissions_validity. # For a longer-running permissions cache, consider setting to update hourly (60000) +# Min unit: ms # permissions_update_interval: 2000ms # If true, cache contents are actively updated by a background task at the @@ -232,6 +241,7 @@ permissions_validity: 2000ms # Defaults to 2000, set to 0 to disable credentials caching. # For a long-running cache using credentials_cache_active_update, consider # setting to something longer such as a daily validation: 86400000 +# Min unit: ms credentials_validity: 2000ms # Refresh interval for credentials cache (if enabled). @@ -243,6 +253,7 @@ credentials_validity: 2000ms # using credentials_cache_active_update. # Defaults to the same value as credentials_validity. # For a longer-running permissions cache, consider setting to update hourly (60000) +# Min unit: ms # credentials_update_interval: 2000ms # If true, cache contents are actively updated by a background task at the @@ -350,6 +361,7 @@ commit_failure_policy: stop # Constantly re-preparing statements is a performance penalty. # # Default value ("auto") is 1/256th of the heap or 10MiB, whichever is greater +# Min unit: MiB # prepared_statements_cache_size: # Maximum size of the key cache in memory. @@ -363,7 +375,8 @@ commit_failure_policy: stop # # NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. # -# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. +# Default value is empty to make it "auto" (min(5% of Heap (in MiB), 100MiB)). Set to 0 to disable key cache. +# Min unit: MiB # key_cache_size: # Duration in seconds after which Cassandra should @@ -375,6 +388,7 @@ commit_failure_policy: stop # has limited use. # # Default is 14400 or 4 hours. +# Min unit: s key_cache_save_period: 4h # Number of keys from the key cache to save @@ -399,6 +413,7 @@ key_cache_save_period: 4h # headroom for OS block level cache. Do never allow your system to swap. # # Default value is 0, to disable row caching. +# Min unit: MiB row_cache_size: 0MiB # Duration in seconds after which Cassandra should save the row cache. @@ -409,6 +424,7 @@ row_cache_size: 0MiB # has limited use. # # Default is 0 to disable saving the row cache. +# Min unit: s row_cache_save_period: 0s # Number of keys from the row cache to save. @@ -426,8 +442,9 @@ row_cache_save_period: 0s # # NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. # -# Default value is empty to make it "auto" (min(2.5% of Heap (in MB), 50MB)). Set to 0 to disable counter cache. +# Default value is empty to make it "auto" (min(2.5% of Heap (in MiB), 50MiB)). Set to 0 to disable counter cache. # NOTE: if you perform counter deletes and rely on low gcgs, you should disable the counter cache. +# Min unit: MiB # counter_cache_size: # Duration in seconds after which Cassandra should @@ -435,6 +452,7 @@ row_cache_save_period: 0s # specified in this configuration file. # # Default is 7200 or 2 hours. +# Min unit: s counter_cache_save_period: 7200s # Number of keys from the counter cache to save @@ -448,6 +466,7 @@ counter_cache_save_period: 7200s # Number of seconds the server will wait for each cache (row, key, etc ...) to load while starting # the Cassandra process. Setting this to zero is equivalent to disabling all cache loading on startup # while still having the cache during runtime. +# Min unit: s # cache_load_timeout: 30s # commitlog_sync may be either "periodic", "group", or "batch." @@ -463,16 +482,19 @@ counter_cache_save_period: 7200s # until the commit log has been flushed to disk. The difference is group # mode will wait up to commitlog_sync_group_window between flushes. # +# Min unit: ms # commitlog_sync_group_window: 1000ms # # the default option is "periodic" where writes may be acked immediately # and the CommitLog is simply synced every commitlog_sync_period # milliseconds. commitlog_sync: periodic +# Min unit: ms commitlog_sync_period: 10000ms # When in periodic commitlog mode, the number of milliseconds to block writes # while waiting for a slow disk flush to complete. +# Min unit: ms # periodic_commitlog_sync_lag_block: # The size of the individual commitlog file segments. A commitlog @@ -491,6 +513,7 @@ commitlog_sync_period: 10000ms # NOTE: If max_mutation_size is set explicitly then commitlog_segment_size must # be set to at least twice the size of max_mutation_size # +# Min unit: MiB commitlog_segment_size: 32MiB # Compression to apply to the commit log. If omitted, the commit log @@ -555,6 +578,7 @@ concurrent_materialized_view_writes: 32 # overhead which is roughly 128 bytes per chunk (i.e. 0.2% of the reserved size # if the default 64k chunk size is used). # Memory is only allocated when needed. +# Min unit: MiB # networking_cache_size: 128MiB # Enable the sstable chunk cache. The chunk cache will store recently accessed @@ -569,6 +593,7 @@ concurrent_materialized_view_writes: 32 # overhead which is roughly 128 bytes per chunk (i.e. 0.2% of the reserved size # if the default 64k chunk size is used). # Memory is only allocated when needed. +# Min unit: MiB # file_cache_size: 512MiB # Flag indicating whether to allocate on or off heap when the sstable buffer @@ -587,7 +612,9 @@ concurrent_materialized_view_writes: 32 # accepting writes when the limit is exceeded until a flush completes, # and will trigger a flush based on memtable_cleanup_threshold # If omitted, Cassandra will set both to 1/4 the size of the heap. +# Min unit: MiB # memtable_heap_space: 2048MiB +# Min unit: MiB # memtable_offheap_space: 2048MiB # memtable_cleanup_threshold is deprecated. The default calculation @@ -625,6 +652,7 @@ memtable_allocation_type: heap_buffers # # For more details see https://issues.apache.org/jira/browse/CASSANDRA-14096. # +# Min unit: MiB # repair_session_space: # Total space to use for commit logs on disk. @@ -675,11 +703,13 @@ memtable_allocation_type: heap_buffers # # The default value is the min of 4096 MiB and 1/8th of the total space # of the drive where cdc_raw_directory resides. +# Min unit: MiB # cdc_total_space: 4096MiB # When we hit our cdc_raw limit and the CDCCompactor is either running behind # or experiencing backpressure, we check at the following interval to see if any # new space for cdc-tracked tables has been made available. Default to 250ms +# Min unit: ms # cdc_free_space_check_interval: 250ms # A fixed memory pool size in MB for for SSTable index summaries. If left @@ -688,12 +718,14 @@ memtable_allocation_type: heap_buffers # shrink their index summaries in order to meet this limit. However, this # is a best-effort process. In extreme conditions Cassandra may need to use # more than this amount of memory. +# Min unit: KiB # index_summary_capacity: # How frequently index summaries should be resampled. This is done # periodically to redistribute memory from the fixed-size pool to sstables # proportional their recent read rates. Setting to -1 will disable this # process, leaving existing index summaries at their current sampling level. +# Min unit: m index_summary_resize_interval: 60m # Whether to, when doing sequential writing, fsync() at intervals in @@ -702,6 +734,7 @@ index_summary_resize_interval: 60m # impacting read latencies. Almost always a good idea on SSDs; not # necessarily on platters. trickle_fsync: false +# Min unit: KiB trickle_fsync_interval: 10240KiB # TCP port, for commands and data @@ -776,6 +809,7 @@ native_transport_port: 9042 # The maximum size of allowed frame. Frame (requests) larger than this will # be rejected as invalid. The default is 16MiB. If you're changing this parameter, # you may want to adjust max_value_size accordingly. This should be positive and less than 2048. +# Min unit: MiB # native_transport_max_frame_size: 16MiB # The maximum number of concurrent client connections. @@ -798,6 +832,7 @@ native_transport_allow_older_protocols: true # values for heartbeat intervals have to be set on the client side. # # Idle connection timeouts are disabled by default. +# Min unit: ms # native_transport_idle_timeout: 60000ms # When enabled, limits the number of native transport requests dispatched for processing per second. @@ -851,11 +886,13 @@ rpc_keepalive: true # /proc/sys/net/ipv4/tcp_wmem # /proc/sys/net/ipv4/tcp_wmem # and 'man tcp' +# Min unit: B # internode_socket_send_buffer_size: # Uncomment to set socket buffer size for internode communication # Note that when setting this, the buffer size is limited by net.core.wmem_max # and when not setting it it is defined by net.ipv4.tcp_wmem +# Min unit: B # internode_socket_receive_buffer_size: # Set to true to have Cassandra create a hard link to each sstable @@ -901,6 +938,7 @@ snapshot_links_per_second: 0 # - but, Cassandra will keep the collation index in memory for hot # rows (as part of the key cache), so a larger granularity means # you can cache more hot rows +# Min unit: KiB column_index_size: 64KiB # Per sstable indexed key cache entries (the collation index in memory @@ -910,6 +948,7 @@ column_index_size: 64KiB # # Note that this size refers to the size of the # serialized index information and not the size of the partition. +# Min unit: KiB column_index_cache_size: 2KiB # Number of simultaneous compactions to allow, NOT including @@ -953,6 +992,7 @@ compaction_throughput: 64MiB/s # are completely written, and used in place of the prior sstables for # any range that has been written. This helps to smoothly transfer reads # between the sstables, reducing page cache churn and keeping hot rows hot +# Min unit: MiB sstable_preemptive_open_interval: 50MiB # Starting from 4.1 sstables support UUID based generation identifiers. They are disabled by default @@ -1014,43 +1054,53 @@ enable_uuid_sstable_identifiers: false # How long the coordinator should wait for read operations to complete. # Lowest acceptable value is 10 ms. +# Min unit: ms read_request_timeout: 5000ms # How long the coordinator should wait for seq or index scans to complete. # Lowest acceptable value is 10 ms. +# Min unit: ms range_request_timeout: 10000ms # How long the coordinator should wait for writes to complete. # Lowest acceptable value is 10 ms. +# Min unit: ms write_request_timeout: 2000ms # How long the coordinator should wait for counter writes to complete. # Lowest acceptable value is 10 ms. +# Min unit: ms counter_write_request_timeout: 5000ms # How long a coordinator should continue to retry a CAS operation # that contends with other proposals for the same row. # Lowest acceptable value is 10 ms. +# Min unit: ms cas_contention_timeout: 1000ms # How long the coordinator should wait for truncates to complete # (This can be much longer, because unless auto_snapshot is disabled # we need to flush first so we can snapshot before removing the data.) # Lowest acceptable value is 10 ms. +# Min unit: ms truncate_request_timeout: 60000ms # The default timeout for other, miscellaneous operations. # Lowest acceptable value is 10 ms. +# Min unit: ms request_timeout: 10000ms # Defensive settings for protecting Cassandra from true network partitions. # See (CASSANDRA-14358) for details. # # The amount of time to wait for internode tcp connections to establish. +# Min unit: ms # internode_tcp_connect_timeout: 2000ms # # The amount of time unacknowledged data is allowed on a connection before we throw out the connection # Note this is only supported on Linux + epoll, and it appears to behave oddly above a setting of 30000 # (it takes much longer than 30s) as of Linux 4.12. If you want something that high set this to 0 # which picks up the OS default and configure the net.ipv4.tcp_retries2 sysctl to be ~8. +# Min unit: ms # internode_tcp_user_timeout: 30000ms # The amount of time unacknowledged data is allowed on a streaming connection. # The default is 5 minutes. Increase it or set it to 0 in order to increase the timeout. +# Min unit: ms # internode_streaming_tcp_user_timeout: 300000ms # Global, per-endpoint and per-connection limits imposed on messages queued for delivery to other nodes @@ -1068,6 +1118,7 @@ request_timeout: 10000ms # The global limit is imposed on all messages exceeding the per-link limit, simultaneously with the per-endpoint limit, # on all links to or from any node in the cluster. # +# Min unit: B # internode_application_send_queue_capacity: 4MiB # internode_application_send_queue_reserve_endpoint_capacity: 128MiB # internode_application_send_queue_reserve_global_capacity: 512MiB @@ -1079,6 +1130,7 @@ request_timeout: 10000ms # How long before a node logs slow queries. Select queries that take longer than # this timeout to execute, will generate an aggregated log message, so that slow queries # can be identified. Set this value to zero to disable slow query logging. +# Min unit: ms slow_query_log_timeout: 500ms # Enable operation timeout information exchange between nodes to accurately @@ -1097,6 +1149,7 @@ slow_query_log_timeout: 500ms # 2 keep-alive cycles the stream session times out and fail # Default value is 300s (5 minutes), which means stalled stream # times out in 10 minutes by default +# Min unit: s # streaming_keep_alive_period: 300s # Limit number of connections per host for streaming @@ -1115,9 +1168,11 @@ slow_query_log_timeout: 500ms # The interval at which keys in the cache for denylisting will "expire" and async refresh from the backing DB. # Note: this serves only as a fail-safe, as the usage pattern is expected to be "mutate state, refresh cache" on any # changes to the underlying denylist entries. See documentation for details. +# Min unit: s # denylist_refresh: 600s # In the event of errors on attempting to load the denylist cache, retry on this interval. +# Min unit: s # denylist_initial_load_retry: 5s # We cap the number of denylisted keys allowed per table to keep things from growing unbounded. Nodes will warn above @@ -1206,9 +1261,11 @@ endpoint_snitch: SimpleSnitch # controls how often to perform the more expensive part of host score # calculation +# Min unit: ms dynamic_snitch_update_interval: 100ms # controls how often to reset all host scores, allowing a bad host to # possibly recover +# Min unit: ms dynamic_snitch_reset_interval: 600000ms # if set greater than zero, this will allow # 'pinning' of replicas to hosts in order to increase cache capacity. @@ -1334,7 +1391,9 @@ internode_compression: dc inter_dc_tcp_nodelay: false # TTL for different trace types used during logging of the repair process. +# Min unit: s trace_type_query_ttl: 1d +# Min unit: s trace_type_repair_ttl: 7d # If unset, all GC Pauses greater than gc_log_threshold will log at @@ -1415,9 +1474,11 @@ replica_filtering_protection: # Log WARN on any multiple-partition batch size exceeding this value. 5KiB per batch by default. # Caution should be taken on increasing the size of this threshold as it can lead to node instability. +# Min unit: KiB batch_size_warn_threshold: 5KiB # Fail any multiple-partition batch exceeding this value. 50KiB (10x warn threshold) by default. +# Min unit: KiB batch_size_fail_threshold: 50KiB # Log WARN on any batches not of type LOGGED than span across more partitions than this limit @@ -1431,16 +1492,19 @@ compaction_tombstone_warning_threshold: 100000 # GC Pauses greater than 200 ms will be logged at INFO level # This threshold can be adjusted to minimize logging if necessary +# Min unit: ms # gc_log_threshold: 200ms # GC Pauses greater than gc_warn_threshold will be logged at WARN level # Adjust the threshold based on your application throughput requirement. Setting to 0 # will deactivate the feature. +# Min unit: ms # gc_warn_threshold: 1000ms # Maximum size of any value in SSTables. Safety measure to detect SSTable corruption # early. Any value size larger than this threshold will result into marking an SSTable # as corrupted. This should be positive and less than 2GiB. +# Min unit: MiB # max_value_size: 256MiB # ** Impact on keyspace creation ** @@ -1676,7 +1740,9 @@ drop_compact_storage_enabled: false # prevent read-before-write. The guardrail is also checked at sstable write time to detect large non-frozen collections, # although in that case exceeding the fail threshold will only log an error message, without interrupting the operation. # The two thresholds default to null to disable. +# Min unit: B # collection_size_warn_threshold: +# Min unit: B # collection_size_fail_threshold: # # Guardrail to warn or fail when encountering more elements in collection than threshold. @@ -1717,6 +1783,7 @@ drop_compact_storage_enabled: false # be useful when we have a large disk and we only want to use a part of it for Cassandra's data directories. # Valid values are in [1, max available disk size of all data directories]. # Defaults to null to disable and use the physically available disk size of data directories during calculations. +# Min unit: B # data_disk_usage_max_disk_size: # # Guardrail to warn or fail when the minimum replication factor is lesser than threshold. diff --git a/doc/modules/cassandra/pages/new/configuration.adoc b/doc/modules/cassandra/pages/new/configuration.adoc index e572778b58..96c53d07ff 100644 --- a/doc/modules/cassandra/pages/new/configuration.adoc +++ b/doc/modules/cassandra/pages/new/configuration.adoc @@ -152,14 +152,22 @@ If the parameter is of type duration, data rate or data storage, its value shoul - Please follow the new format `noun_verb` when adding new configuration parameters. -- Please consider adding any new parameters with the lowest supported by Cassandra unit. +- Please consider adding any new parameters with the lowest supported by Cassandra unit when possible. Our new types also +support long and integer upper bound, depending on your needs. All options for configuration parameters' types are nested +classes in our three main abstract classes - `DurationSpec`, `DataStorageSpec`, `DataRateSpec`. -- If for some reason you consider the smallest unit shouldn’t be the one that is supported as such in Cassandra, please, -use the extended classes `SmallestDuration*`, `SmallestDataStorage*`. +- If for some reason you consider the smallest unit for a new parameter shouldn’t be the one that is supported as such in +Cassandra, you can use the rest of the nested classes in `DurationSpec`, `DataStorageSpec`. The smallest allowed unit is +the one we use internally for the property, so we don't have to do conversions to bigger units which will lead to precision +problems. This is a problem only with `DurationSpec` and `DataStorageSpec`. `DataRateSpec` is handled internally in double. - New parameters should be added as non-negative numbers. For parameters where you would have set -1 to disable in the past, you might want to consider a separate flag parameter or null value. In case you use the null value, please, ensure that any default value -introduced in the DatabaDescriptor to handle it is also duplicated in any related setters. +introduced in the DatabaseDescriptor to handle it is also duplicated in any related setters. + +- Parameters of type data storage, duration and data rate cannot be set to Long.MAX_VALUE (former parameters of long type) +and Integer.MAX_VALUE (former parameters of int type). That numbers are used during conversion between units to prevent +an overflow from happening. - Any time you add @Replaces with a name change, we need to add an entry in this https://github.com/riptano/ccm/blob/808b6ca13526785b0fddfe1ead2383c060c4b8b6/ccmlib/common.py#L62[Python dictionary in CCM] to support the same backward compatibility as SnakeYAML. @@ -194,3 +202,6 @@ hinted_handoff_enabled: false .... https://issues.apache.org/jira/browse/CASSANDRA-17379[CASSANDRA-17379] was opened to improve the user experience and deprecate the overloading. +By default, we refuse starting Cassandra with a config containing both old and new config keys for the same parameter. Start +Cassandra with `-Dcassandra.allow_new_old_config_keys=true` to override. For historical reasons duplicate config keys +in `cassandra.yaml` are allowed by default, start Cassandra with `-Dcassandra.allow_duplicate_config_keys=false` to disallow this. \ No newline at end of file diff --git a/src/java/org/apache/cassandra/auth/AuthConfig.java b/src/java/org/apache/cassandra/auth/AuthConfig.java index c4b71eb152..9c5fceb6dc 100644 --- a/src/java/org/apache/cassandra/auth/AuthConfig.java +++ b/src/java/org/apache/cassandra/auth/AuthConfig.java @@ -57,7 +57,7 @@ public final class AuthConfig // is in use and non-default values are detected if (!(authenticator instanceof PasswordAuthenticator) && (conf.credentials_update_interval != null - || conf.credentials_validity.toMillisecondsAsInt() != 2000 + || conf.credentials_validity.toMilliseconds() != 2000 || conf.credentials_cache_max_entries != 1000)) { logger.info("Configuration options credentials_update_interval, credentials_validity and " + diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index 3bca7e3502..9f75a277bc 100644 --- a/src/java/org/apache/cassandra/config/Config.java +++ b/src/java/org/apache/cassandra/config/Config.java @@ -74,22 +74,22 @@ public class Config public String role_manager; public String network_authorizer; @Replaces(oldName = "permissions_validity_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds permissions_validity = new SmallestDurationMilliseconds("2s"); + public volatile DurationSpec.IntMillisecondsBound permissions_validity = new DurationSpec.IntMillisecondsBound("2s"); public volatile int permissions_cache_max_entries = 1000; @Replaces(oldName = "permissions_update_interval_in_ms", converter = Converters.MILLIS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationMilliseconds permissions_update_interval = null; + public volatile DurationSpec.IntMillisecondsBound permissions_update_interval = null; public volatile boolean permissions_cache_active_update = false; @Replaces(oldName = "roles_validity_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds roles_validity = new SmallestDurationMilliseconds("2s"); + public volatile DurationSpec.IntMillisecondsBound roles_validity = new DurationSpec.IntMillisecondsBound("2s"); public volatile int roles_cache_max_entries = 1000; @Replaces(oldName = "roles_update_interval_in_ms", converter = Converters.MILLIS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationMilliseconds roles_update_interval = null; + public volatile DurationSpec.IntMillisecondsBound roles_update_interval = null; public volatile boolean roles_cache_active_update = false; @Replaces(oldName = "credentials_validity_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds credentials_validity = new SmallestDurationMilliseconds("2s"); + public volatile DurationSpec.IntMillisecondsBound credentials_validity = new DurationSpec.IntMillisecondsBound("2s"); public volatile int credentials_cache_max_entries = 1000; @Replaces(oldName = "credentials_update_interval_in_ms", converter = Converters.MILLIS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationMilliseconds credentials_update_interval = null; + public volatile DurationSpec.IntMillisecondsBound credentials_update_interval = null; public volatile boolean credentials_cache_active_update = false; /* Hashing strategy Random or OPHF */ @@ -99,7 +99,7 @@ public class Config public volatile boolean hinted_handoff_enabled = true; public Set hinted_handoff_disabled_datacenters = Sets.newConcurrentHashSet(); @Replaces(oldName = "max_hint_window_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds max_hint_window = new SmallestDurationMilliseconds("3h"); + public volatile DurationSpec.IntMillisecondsBound max_hint_window = new DurationSpec.IntMillisecondsBound("3h"); public String hints_directory; public boolean hint_window_persistent_enabled = true; @@ -122,40 +122,40 @@ public class Config public Integer allocate_tokens_for_local_replication_factor = null; @Replaces(oldName = "native_transport_idle_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public SmallestDurationMilliseconds native_transport_idle_timeout = new SmallestDurationMilliseconds("0ms"); + public DurationSpec.LongMillisecondsBound native_transport_idle_timeout = new DurationSpec.LongMillisecondsBound("0ms"); @Replaces(oldName = "request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds request_timeout = new SmallestDurationMilliseconds("10000ms"); + public volatile DurationSpec.LongMillisecondsBound request_timeout = new DurationSpec.LongMillisecondsBound("10000ms"); @Replaces(oldName = "read_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds read_request_timeout = new SmallestDurationMilliseconds("5000ms"); + public volatile DurationSpec.LongMillisecondsBound read_request_timeout = new DurationSpec.LongMillisecondsBound("5000ms"); @Replaces(oldName = "range_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds range_request_timeout = new SmallestDurationMilliseconds("10000ms"); + public volatile DurationSpec.LongMillisecondsBound range_request_timeout = new DurationSpec.LongMillisecondsBound("10000ms"); @Replaces(oldName = "write_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds write_request_timeout = new SmallestDurationMilliseconds("2000ms"); + public volatile DurationSpec.LongMillisecondsBound write_request_timeout = new DurationSpec.LongMillisecondsBound("2000ms"); @Replaces(oldName = "counter_write_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds counter_write_request_timeout = new SmallestDurationMilliseconds("5000ms"); + public volatile DurationSpec.LongMillisecondsBound counter_write_request_timeout = new DurationSpec.LongMillisecondsBound("5000ms"); @Replaces(oldName = "cas_contention_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds cas_contention_timeout = new SmallestDurationMilliseconds("1800ms"); + public volatile DurationSpec.LongMillisecondsBound cas_contention_timeout = new DurationSpec.LongMillisecondsBound("1800ms"); @Replaces(oldName = "truncate_request_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds truncate_request_timeout = new SmallestDurationMilliseconds("60000ms"); + public volatile DurationSpec.LongMillisecondsBound truncate_request_timeout = new DurationSpec.LongMillisecondsBound("60000ms"); - public volatile SmallestDurationMilliseconds repair_request_timeout = new SmallestDurationMilliseconds("120000ms"); + public volatile DurationSpec.LongMillisecondsBound repair_request_timeout = new DurationSpec.LongMillisecondsBound("120000ms"); public Integer streaming_connections_per_host = 1; @Replaces(oldName = "streaming_keep_alive_period_in_secs", converter = Converters.SECONDS_DURATION, deprecated = true) - public SmallestDurationSeconds streaming_keep_alive_period = new SmallestDurationSeconds("300s"); + public DurationSpec.IntSecondsBound streaming_keep_alive_period = new DurationSpec.IntSecondsBound("300s"); @Replaces(oldName = "cross_node_timeout", converter = Converters.IDENTITY, deprecated = true) public boolean internode_timeout = true; @Replaces(oldName = "slow_query_log_timeout_in_ms", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public volatile SmallestDurationMilliseconds slow_query_log_timeout = new SmallestDurationMilliseconds("500ms"); + public volatile DurationSpec.LongMillisecondsBound slow_query_log_timeout = new DurationSpec.LongMillisecondsBound("500ms"); public volatile double phi_convict_threshold = 8.0; @@ -170,9 +170,9 @@ public class Config public int memtable_flush_writers = 0; @Replaces(oldName = "memtable_heap_space_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes memtable_heap_space; + public DataStorageSpec.IntMebibytesBound memtable_heap_space; @Replaces(oldName = "memtable_offheap_space_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes memtable_offheap_space; + public DataStorageSpec.IntMebibytesBound memtable_offheap_space; public Float memtable_cleanup_threshold = null; public static class MemtableOptions @@ -190,7 +190,7 @@ public class Config @Deprecated public volatile Integer repair_session_max_tree_depth = null; @Replaces(oldName = "repair_session_space_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public volatile SmallestDataStorageMebibytes repair_session_space = null; + public volatile DataStorageSpec.IntMebibytesBound repair_session_space = null; public volatile boolean use_offheap_merkle_trees = true; @@ -219,51 +219,51 @@ public class Config public boolean rpc_keepalive = true; @Replaces(oldName = "internode_max_message_size_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated=true) - public DataStorageSpec internode_max_message_size; + public DataStorageSpec.IntBytesBound internode_max_message_size; @Replaces(oldName = "internode_socket_send_buffer_size_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) @Replaces(oldName = "internode_send_buff_size_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_socket_send_buffer_size = new DataStorageSpec("0B"); + public DataStorageSpec.IntBytesBound internode_socket_send_buffer_size = new DataStorageSpec.IntBytesBound("0B"); @Replaces(oldName = "internode_socket_receive_buffer_size_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) @Replaces(oldName = "internode_recv_buff_size_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_socket_receive_buffer_size = new DataStorageSpec("0B"); + public DataStorageSpec.IntBytesBound internode_socket_receive_buffer_size = new DataStorageSpec.IntBytesBound("0B"); // TODO: derive defaults from system memory settings? @Replaces(oldName = "internode_application_send_queue_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_send_queue_capacity = new DataStorageSpec("4MiB"); + public DataStorageSpec.IntBytesBound internode_application_send_queue_capacity = new DataStorageSpec.IntBytesBound("4MiB"); @Replaces(oldName = "internode_application_send_queue_reserve_endpoint_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_send_queue_reserve_endpoint_capacity = new DataStorageSpec("128MiB"); + public DataStorageSpec.IntBytesBound internode_application_send_queue_reserve_endpoint_capacity = new DataStorageSpec.IntBytesBound("128MiB"); @Replaces(oldName = "internode_application_send_queue_reserve_global_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_send_queue_reserve_global_capacity = new DataStorageSpec("512MiB"); + public DataStorageSpec.IntBytesBound internode_application_send_queue_reserve_global_capacity = new DataStorageSpec.IntBytesBound("512MiB"); @Replaces(oldName = "internode_application_receive_queue_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_receive_queue_capacity = new DataStorageSpec("4MiB"); + public DataStorageSpec.IntBytesBound internode_application_receive_queue_capacity = new DataStorageSpec.IntBytesBound("4MiB"); @Replaces(oldName = "internode_application_receive_queue_reserve_endpoint_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_receive_queue_reserve_endpoint_capacity = new DataStorageSpec("128MiB"); + public DataStorageSpec.IntBytesBound internode_application_receive_queue_reserve_endpoint_capacity = new DataStorageSpec.IntBytesBound("128MiB"); @Replaces(oldName = "internode_application_receive_queue_reserve_global_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec internode_application_receive_queue_reserve_global_capacity = new DataStorageSpec("512MiB"); + public DataStorageSpec.IntBytesBound internode_application_receive_queue_reserve_global_capacity = new DataStorageSpec.IntBytesBound("512MiB"); // Defensive settings for protecting Cassandra from true network partitions. See (CASSANDRA-14358) for details. // The amount of time to wait for internode tcp connections to establish. @Replaces(oldName = "internode_tcp_connect_timeout_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds internode_tcp_connect_timeout = new SmallestDurationMilliseconds("2s"); + public volatile DurationSpec.IntMillisecondsBound internode_tcp_connect_timeout = new DurationSpec.IntMillisecondsBound("2s"); // The amount of time unacknowledged data is allowed on a connection before we throw out the connection // Note this is only supported on Linux + epoll, and it appears to behave oddly above a setting of 30000 // (it takes much longer than 30s) as of Linux 4.12. If you want something that high set this to 0 // (which picks up the OS default) and configure the net.ipv4.tcp_retries2 sysctl to be ~8. @Replaces(oldName = "internode_tcp_user_timeout_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds internode_tcp_user_timeout = new SmallestDurationMilliseconds("30s"); + public volatile DurationSpec.IntMillisecondsBound internode_tcp_user_timeout = new DurationSpec.IntMillisecondsBound("30s"); // Similar to internode_tcp_user_timeout but used specifically for streaming connection. // The default is 5 minutes. Increase it or set it to 0 in order to increase the timeout. @Replaces(oldName = "internode_streaming_tcp_user_timeout_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public volatile SmallestDurationMilliseconds internode_streaming_tcp_user_timeout = new SmallestDurationMilliseconds("300s"); // 5 minutes + public volatile DurationSpec.IntMillisecondsBound internode_streaming_tcp_user_timeout = new DurationSpec.IntMillisecondsBound("300s"); // 5 minutes public boolean start_native_transport = true; public int native_transport_port = 9042; public Integer native_transport_port_ssl = null; public int native_transport_max_threads = 128; @Replaces(oldName = "native_transport_max_frame_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes native_transport_max_frame_size = new SmallestDataStorageMebibytes("16MiB"); + public DataStorageSpec.IntMebibytesBound native_transport_max_frame_size = new DataStorageSpec.IntMebibytesBound("16MiB"); public volatile long native_transport_max_concurrent_connections = -1L; public volatile long native_transport_max_concurrent_connections_per_ip = -1L; public boolean native_transport_flush_in_batches_legacy = false; @@ -271,13 +271,13 @@ public class Config // Below 2 parameters were fixed in 4.0 + to get default value when ==-1 (old name and value format) or ==null(new name and value format), // not <=0 as it is in previous versions. Throwing config exceptions on < -1 @Replaces(oldName = "native_transport_max_concurrent_requests_in_bytes_per_ip", converter = Converters.BYTES_CUSTOM_DATASTORAGE, deprecated = true) - public volatile DataStorageSpec native_transport_max_request_data_in_flight_per_ip = null; + public volatile DataStorageSpec.LongBytesBound native_transport_max_request_data_in_flight_per_ip = null; @Replaces(oldName = "native_transport_max_concurrent_requests_in_bytes", converter = Converters.BYTES_CUSTOM_DATASTORAGE, deprecated = true) - public volatile DataStorageSpec native_transport_max_request_data_in_flight = null; + public volatile DataStorageSpec.LongBytesBound native_transport_max_request_data_in_flight = null; public volatile boolean native_transport_rate_limiting_enabled = false; public volatile int native_transport_max_requests_per_second = 1000000; @Replaces(oldName = "native_transport_receive_queue_capacity_in_bytes", converter = Converters.BYTES_DATASTORAGE, deprecated = true) - public DataStorageSpec native_transport_receive_queue_capacity = new DataStorageSpec("1MiB"); + public DataStorageSpec.IntBytesBound native_transport_receive_queue_capacity = new DataStorageSpec.IntBytesBound("1MiB"); @Deprecated public Integer native_transport_max_negotiable_protocol_version = null; @@ -288,7 +288,7 @@ public class Config * See AbstractType for how it is used. */ @Replaces(oldName = "max_value_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes max_value_size = new SmallestDataStorageMebibytes("256MiB"); + public DataStorageSpec.IntMebibytesBound max_value_size = new DataStorageSpec.IntMebibytesBound("256MiB"); public boolean snapshot_before_compaction = false; public boolean auto_snapshot = true; @@ -304,22 +304,22 @@ public class Config /* if the size of columns or super-columns are more than this, indexing will kick in */ @Replaces(oldName = "column_index_size_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public volatile SmallestDataStorageKibibytes column_index_size = new SmallestDataStorageKibibytes("64KiB"); + public volatile DataStorageSpec.IntKibibytesBound column_index_size = new DataStorageSpec.IntKibibytesBound("64KiB"); @Replaces(oldName = "column_index_cache_size_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public volatile SmallestDataStorageKibibytes column_index_cache_size = new SmallestDataStorageKibibytes("2KiB"); + public volatile DataStorageSpec.IntKibibytesBound column_index_cache_size = new DataStorageSpec.IntKibibytesBound("2KiB"); @Replaces(oldName = "batch_size_warn_threshold_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public volatile SmallestDataStorageKibibytes batch_size_warn_threshold = new SmallestDataStorageKibibytes("5KiB"); + public volatile DataStorageSpec.IntKibibytesBound batch_size_warn_threshold = new DataStorageSpec.IntKibibytesBound("5KiB"); @Replaces(oldName = "batch_size_fail_threshold_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public volatile SmallestDataStorageKibibytes batch_size_fail_threshold = new SmallestDataStorageKibibytes("50KiB"); + public volatile DataStorageSpec.IntKibibytesBound batch_size_fail_threshold = new DataStorageSpec.IntKibibytesBound("50KiB"); public Integer unlogged_batch_across_partitions_warn_threshold = 10; public volatile Integer concurrent_compactors; @Replaces(oldName = "compaction_throughput_mb_per_sec", converter = Converters.MEBIBYTES_PER_SECOND_DATA_RATE, deprecated = true) - public volatile DataRateSpec compaction_throughput = new DataRateSpec("16MiB/s"); + public volatile DataRateSpec.IntMebibytesPerSecondBound compaction_throughput = new DataRateSpec.IntMebibytesPerSecondBound("16MiB/s"); @Replaces(oldName = "compaction_large_partition_warning_threshold_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public volatile SmallestDataStorageMebibytes compaction_large_partition_warning_threshold = new SmallestDataStorageMebibytes("100MiB"); + public volatile DataStorageSpec.IntMebibytesBound compaction_large_partition_warning_threshold = new DataStorageSpec.IntMebibytesBound("100MiB"); @Replaces(oldName = "min_free_space_per_drive_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes min_free_space_per_drive = new SmallestDataStorageMebibytes("50MiB"); + public DataStorageSpec.IntMebibytesBound min_free_space_per_drive = new DataStorageSpec.IntMebibytesBound("50MiB"); public volatile Integer compaction_tombstone_warning_threshold = 100000; public volatile int concurrent_materialized_view_builders = 1; @@ -332,12 +332,12 @@ public class Config public int max_streaming_retries = 3; @Replaces(oldName = "stream_throughput_outbound_megabits_per_sec", converter = Converters.MEGABITS_TO_MEBIBYTES_PER_SECOND_DATA_RATE, deprecated = true) - public volatile DataRateSpec stream_throughput_outbound = new DataRateSpec("24MiB/s"); + public volatile DataRateSpec.IntMebibytesPerSecondBound stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s"); @Replaces(oldName = "inter_dc_stream_throughput_outbound_megabits_per_sec", converter = Converters.MEGABITS_TO_MEBIBYTES_PER_SECOND_DATA_RATE, deprecated = true) - public volatile DataRateSpec inter_dc_stream_throughput_outbound = new DataRateSpec("24MiB/s"); + public volatile DataRateSpec.IntMebibytesPerSecondBound inter_dc_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s"); - public volatile DataRateSpec entire_sstable_stream_throughput_outbound = new DataRateSpec("24MiB/s"); - public volatile DataRateSpec entire_sstable_inter_dc_stream_throughput_outbound = new DataRateSpec("24MiB/s"); + public volatile DataRateSpec.IntMebibytesPerSecondBound entire_sstable_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s"); + public volatile DataRateSpec.IntMebibytesPerSecondBound entire_sstable_inter_dc_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s"); public String[] data_file_directories = new String[0]; @@ -352,7 +352,7 @@ public class Config // Commit Log public String commitlog_directory; @Replaces(oldName = "commitlog_total_space_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes commitlog_total_space; + public DataStorageSpec.IntMebibytesBound commitlog_total_space; public CommitLogSync commitlog_sync; /** @@ -360,20 +360,20 @@ public class Config */ public double commitlog_sync_batch_window_in_ms = Double.NaN; @Replaces(oldName = "commitlog_sync_group_window_in_ms", converter = Converters.MILLIS_DURATION_DOUBLE, deprecated = true) - public SmallestDurationMilliseconds commitlog_sync_group_window = new SmallestDurationMilliseconds("0ms"); + public DurationSpec.IntMillisecondsBound commitlog_sync_group_window = new DurationSpec.IntMillisecondsBound("0ms"); @Replaces(oldName = "commitlog_sync_period_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds commitlog_sync_period = new SmallestDurationMilliseconds("0ms"); + public DurationSpec.IntMillisecondsBound commitlog_sync_period = new DurationSpec.IntMillisecondsBound("0ms"); @Replaces(oldName = "commitlog_segment_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes commitlog_segment_size = new SmallestDataStorageMebibytes("32MiB"); + public DataStorageSpec.IntMebibytesBound commitlog_segment_size = new DataStorageSpec.IntMebibytesBound("32MiB"); public ParameterizedClass commitlog_compression; public FlushCompression flush_compression = FlushCompression.fast; public int commitlog_max_compression_buffers_in_pool = 3; @Replaces(oldName = "periodic_commitlog_sync_lag_block_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds periodic_commitlog_sync_lag_block; + public DurationSpec.IntMillisecondsBound periodic_commitlog_sync_lag_block; public TransparentDataEncryptionOptions transparent_data_encryption_options = new TransparentDataEncryptionOptions(); @Replaces(oldName = "max_mutation_size_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public SmallestDataStorageKibibytes max_mutation_size; + public DataStorageSpec.IntKibibytesBound max_mutation_size; // Change-data-capture logs public boolean cdc_enabled = false; @@ -382,9 +382,9 @@ public class Config public volatile boolean cdc_block_writes = true; public String cdc_raw_directory; @Replaces(oldName = "cdc_total_space_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes cdc_total_space = new SmallestDataStorageMebibytes("0MiB"); + public DataStorageSpec.IntMebibytesBound cdc_total_space = new DataStorageSpec.IntMebibytesBound("0MiB"); @Replaces(oldName = "cdc_free_space_check_interval_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds cdc_free_space_check_interval = new SmallestDurationMilliseconds("250ms"); + public DurationSpec.IntMillisecondsBound cdc_free_space_check_interval = new DurationSpec.IntMillisecondsBound("250ms"); @Deprecated public int commitlog_periodic_queue_size = -1; @@ -392,9 +392,9 @@ public class Config public String endpoint_snitch; public boolean dynamic_snitch = true; @Replaces(oldName = "dynamic_snitch_update_interval_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds dynamic_snitch_update_interval = new SmallestDurationMilliseconds("100ms"); + public DurationSpec.IntMillisecondsBound dynamic_snitch_update_interval = new DurationSpec.IntMillisecondsBound("100ms"); @Replaces(oldName = "dynamic_snitch_reset_interval_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds dynamic_snitch_reset_interval = new SmallestDurationMilliseconds("10m"); + public DurationSpec.IntMillisecondsBound dynamic_snitch_reset_interval = new DurationSpec.IntMillisecondsBound("10m"); public double dynamic_snitch_badness_threshold = 1.0; public String failure_detector = "FailureDetector"; @@ -405,15 +405,15 @@ public class Config public InternodeCompression internode_compression = InternodeCompression.none; @Replaces(oldName = "hinted_handoff_throttle_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public SmallestDataStorageKibibytes hinted_handoff_throttle = new SmallestDataStorageKibibytes("1024KiB"); + public DataStorageSpec.IntKibibytesBound hinted_handoff_throttle = new DataStorageSpec.IntKibibytesBound("1024KiB"); @Replaces(oldName = "batchlog_replay_throttle_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public SmallestDataStorageKibibytes batchlog_replay_throttle = new SmallestDataStorageKibibytes("1024KiB"); + public DataStorageSpec.IntKibibytesBound batchlog_replay_throttle = new DataStorageSpec.IntKibibytesBound("1024KiB"); public int max_hints_delivery_threads = 2; @Replaces(oldName = "hints_flush_period_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds hints_flush_period = new SmallestDurationMilliseconds("10s"); + public DurationSpec.IntMillisecondsBound hints_flush_period = new DurationSpec.IntMillisecondsBound("10s"); @Replaces(oldName = "max_hints_file_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes max_hints_file_size = new SmallestDataStorageMebibytes("128MiB"); - public volatile DataStorageSpec max_hints_size_per_host = new DataStorageSpec("0B"); // 0 means disabled + public DataStorageSpec.IntMebibytesBound max_hints_file_size = new DataStorageSpec.IntMebibytesBound("128MiB"); + public volatile DataStorageSpec.LongBytesBound max_hints_size_per_host = new DataStorageSpec.LongBytesBound("0B"); // 0 means disabled public ParameterizedClass hints_compression; public volatile boolean auto_hints_cleanup_enabled = false; @@ -421,44 +421,44 @@ public class Config public volatile boolean incremental_backups = false; public boolean trickle_fsync = false; @Replaces(oldName = "trickle_fsync_interval_in_kb", converter = Converters.KIBIBYTES_DATASTORAGE, deprecated = true) - public SmallestDataStorageKibibytes trickle_fsync_interval = new SmallestDataStorageKibibytes("10240KiB"); + public DataStorageSpec.IntKibibytesBound trickle_fsync_interval = new DataStorageSpec.IntKibibytesBound("10240KiB"); @Replaces(oldName = "sstable_preemptive_open_interval_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public volatile SmallestDataStorageMebibytes sstable_preemptive_open_interval = new SmallestDataStorageMebibytes("50MiB"); + public volatile DataStorageSpec.IntMebibytesBound sstable_preemptive_open_interval = new DataStorageSpec.IntMebibytesBound("50MiB"); public volatile boolean key_cache_migrate_during_compaction = true; public volatile int key_cache_keys_to_save = Integer.MAX_VALUE; @Replaces(oldName = "key_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) - public SmallestDataStorageMebibytes key_cache_size = null; + public DataStorageSpec.LongMebibytesBound key_cache_size = null; @Replaces(oldName = "key_cache_save_period", converter = Converters.SECONDS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationSeconds key_cache_save_period = new SmallestDurationSeconds("4h"); + public volatile DurationSpec.IntSecondsBound key_cache_save_period = new DurationSpec.IntSecondsBound("4h"); public String row_cache_class_name = "org.apache.cassandra.cache.OHCProvider"; @Replaces(oldName = "row_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) - public SmallestDataStorageMebibytes row_cache_size = new SmallestDataStorageMebibytes("0MiB"); + public DataStorageSpec.LongMebibytesBound row_cache_size = new DataStorageSpec.LongMebibytesBound("0MiB"); @Replaces(oldName = "row_cache_save_period", converter = Converters.SECONDS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationSeconds row_cache_save_period = new SmallestDurationSeconds("0s"); + public volatile DurationSpec.IntSecondsBound row_cache_save_period = new DurationSpec.IntSecondsBound("0s"); public volatile int row_cache_keys_to_save = Integer.MAX_VALUE; @Replaces(oldName = "counter_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) - public SmallestDataStorageMebibytes counter_cache_size = null; + public DataStorageSpec.LongMebibytesBound counter_cache_size = null; @Replaces(oldName = "counter_cache_save_period", converter = Converters.SECONDS_CUSTOM_DURATION, deprecated = true) - public volatile SmallestDurationSeconds counter_cache_save_period = new SmallestDurationSeconds("7200s"); + public volatile DurationSpec.IntSecondsBound counter_cache_save_period = new DurationSpec.IntSecondsBound("7200s"); public volatile int counter_cache_keys_to_save = Integer.MAX_VALUE; - public SmallestDataStorageMebibytes paxos_cache_size = null; + public DataStorageSpec.LongMebibytesBound paxos_cache_size = null; @Replaces(oldName = "cache_load_timeout_seconds", converter = Converters.SECONDS_DURATION, deprecated = true) - public SmallestDurationSeconds cache_load_timeout = new SmallestDurationSeconds("30s"); + public DurationSpec.IntSecondsBound cache_load_timeout = new DurationSpec.IntSecondsBound("30s"); private static boolean isClientMode = false; private static Supplier overrideLoadConfig = null; @Replaces(oldName = "networking_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes networking_cache_size; + public DataStorageSpec.IntMebibytesBound networking_cache_size; @Replaces(oldName = "file_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_INT, deprecated = true) - public SmallestDataStorageMebibytes file_cache_size; + public DataStorageSpec.IntMebibytesBound file_cache_size; public boolean file_cache_enabled = Boolean.getBoolean("cassandra.file_cache_enabled"); @@ -487,12 +487,12 @@ public class Config public MemtableAllocationType memtable_allocation_type = MemtableAllocationType.heap_buffers; public volatile boolean read_thresholds_enabled = false; - public volatile DataStorageSpec coordinator_read_size_warn_threshold = null; - public volatile DataStorageSpec coordinator_read_size_fail_threshold = null; - public volatile DataStorageSpec local_read_size_warn_threshold = null; - public volatile DataStorageSpec local_read_size_fail_threshold = null; - public volatile DataStorageSpec row_index_read_size_warn_threshold = null; - public volatile DataStorageSpec row_index_read_size_fail_threshold = null; + public volatile DataStorageSpec.LongBytesBound coordinator_read_size_warn_threshold = null; + public volatile DataStorageSpec.LongBytesBound coordinator_read_size_fail_threshold = null; + public volatile DataStorageSpec.LongBytesBound local_read_size_warn_threshold = null; + public volatile DataStorageSpec.LongBytesBound local_read_size_fail_threshold = null; + public volatile DataStorageSpec.LongBytesBound row_index_read_size_warn_threshold = null; + public volatile DataStorageSpec.LongBytesBound row_index_read_size_fail_threshold = null; public volatile int tombstone_warn_threshold = 1000; public volatile int tombstone_failure_threshold = 100000; @@ -500,20 +500,20 @@ public class Config public final ReplicaFilteringProtectionOptions replica_filtering_protection = new ReplicaFilteringProtectionOptions(); @Replaces(oldName = "index_summary_capacity_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) - public volatile SmallestDataStorageMebibytes index_summary_capacity; + public volatile DataStorageSpec.LongMebibytesBound index_summary_capacity; @Replaces(oldName = "index_summary_resize_interval_in_minutes", converter = Converters.MINUTES_DURATION, deprecated = true) - public volatile SmallestDurationMinutes index_summary_resize_interval = new SmallestDurationMinutes("60m"); + public volatile DurationSpec.IntMinutesBound index_summary_resize_interval = new DurationSpec.IntMinutesBound("60m"); @Replaces(oldName = "gc_log_threshold_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds gc_log_threshold = new SmallestDurationMilliseconds("200ms"); + public DurationSpec.IntMillisecondsBound gc_log_threshold = new DurationSpec.IntMillisecondsBound("200ms"); @Replaces(oldName = "gc_warn_threshold_in_ms", converter = Converters.MILLIS_DURATION_INT, deprecated = true) - public SmallestDurationMilliseconds gc_warn_threshold = new SmallestDurationMilliseconds("1s"); + public DurationSpec.IntMillisecondsBound gc_warn_threshold = new DurationSpec.IntMillisecondsBound("1s"); // TTL for different types of trace events. @Replaces(oldName = "tracetype_query_ttl", converter = Converters.SECONDS_DURATION, deprecated=true) - public SmallestDurationSeconds trace_type_query_ttl = new SmallestDurationSeconds("1d"); + public DurationSpec.IntSecondsBound trace_type_query_ttl = new DurationSpec.IntSecondsBound("1d"); @Replaces(oldName = "tracetype_repair_ttl", converter = Converters.SECONDS_DURATION, deprecated=true) - public SmallestDurationSeconds trace_type_repair_ttl = new SmallestDurationSeconds("7d"); + public DurationSpec.IntSecondsBound trace_type_repair_ttl = new DurationSpec.IntSecondsBound("7d"); /** * Maintain statistics on whether writes achieve the ideal consistency level @@ -543,7 +543,7 @@ public class Config * Defaults to 1/256th of the heap size or 10MiB, whichever is greater. */ @Replaces(oldName = "prepared_statements_cache_size_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) - public SmallestDataStorageMebibytes prepared_statements_cache_size = null; + public DataStorageSpec.LongMebibytesBound prepared_statements_cache_size = null; @Replaces(oldName = "enable_user_defined_functions", converter = Converters.IDENTITY, deprecated = true) public boolean user_defined_functions_enabled = false; @@ -595,14 +595,14 @@ public class Config * (Only valid, if user_defined_functions_threads_enabled==true) */ @Replaces(oldName = "user_defined_function_warn_timeout", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public SmallestDurationMilliseconds user_defined_functions_warn_timeout = new SmallestDurationMilliseconds("500ms"); + public DurationSpec.LongMillisecondsBound user_defined_functions_warn_timeout = new DurationSpec.LongMillisecondsBound("500ms"); /** * Time in milliseconds after a fatal UDF run-time situation is detected and action according to * user_function_timeout_policy will take place. * (Only valid, if user_defined_functions_threads_enabled==true) */ @Replaces(oldName = "user_defined_function_fail_timeout", converter = Converters.MILLIS_DURATION_LONG, deprecated = true) - public SmallestDurationMilliseconds user_defined_functions_fail_timeout = new SmallestDurationMilliseconds("1500ms"); + public DurationSpec.LongMillisecondsBound user_defined_functions_fail_timeout = new DurationSpec.LongMillisecondsBound("1500ms"); /** * Defines what to do when a UDF ran longer than user_defined_functions_fail_timeout. * Possible options are: @@ -692,7 +692,7 @@ public class Config */ @Replaces(oldName = "validation_preview_purge_head_start_in_sec", converter = Converters.NEGATIVE_SECONDS_DURATION, deprecated = true) - public volatile SmallestDurationSeconds validation_preview_purge_head_start = new SmallestDurationSeconds("3600s"); + public volatile DurationSpec.IntSecondsBound validation_preview_purge_head_start = new DurationSpec.IntSecondsBound("3600s"); public boolean auth_cache_warming_enabled = false; @@ -712,9 +712,9 @@ public class Config public volatile boolean denylist_range_reads_enabled = true; - public SmallestDurationSeconds denylist_refresh = new SmallestDurationSeconds("600s"); + public DurationSpec.IntSecondsBound denylist_refresh = new DurationSpec.IntSecondsBound("600s"); - public SmallestDurationSeconds denylist_initial_load_retry = new SmallestDurationSeconds("5s"); + public DurationSpec.IntSecondsBound denylist_initial_load_retry = new DurationSpec.IntSecondsBound("5s"); /** We cap the number of denylisted keys allowed per table to keep things from growing unbounded. Operators will * receive warnings and only denylist_max_keys_per_table in natural query ordering will be processed on overflow. @@ -833,25 +833,25 @@ public class Config public volatile boolean compact_tables_enabled = true; public volatile boolean read_before_write_list_operations_enabled = true; public volatile boolean allow_filtering_enabled = true; - public volatile DataStorageSpec collection_size_warn_threshold = null; - public volatile DataStorageSpec collection_size_fail_threshold = null; + public volatile DataStorageSpec.LongBytesBound collection_size_warn_threshold = null; + public volatile DataStorageSpec.LongBytesBound collection_size_fail_threshold = null; public volatile int items_per_collection_warn_threshold = -1; public volatile int items_per_collection_fail_threshold = -1; public volatile int fields_per_udt_warn_threshold = -1; public volatile int fields_per_udt_fail_threshold = -1; public volatile int data_disk_usage_percentage_warn_threshold = -1; public volatile int data_disk_usage_percentage_fail_threshold = -1; - public volatile DataStorageSpec data_disk_usage_max_disk_size = null; + public volatile DataStorageSpec.LongBytesBound data_disk_usage_max_disk_size = null; public volatile int minimum_replication_factor_warn_threshold = -1; public volatile int minimum_replication_factor_fail_threshold = -1; - public volatile DurationSpec streaming_state_expires = DurationSpec.inDays(3); - public volatile DataStorageSpec streaming_state_size = DataStorageSpec.inMebibytes(40); + public volatile DurationSpec.LongNanosecondsBound streaming_state_expires = new DurationSpec.LongNanosecondsBound("3d"); + public volatile DataStorageSpec.LongBytesBound streaming_state_size = new DataStorageSpec.LongBytesBound("40MiB"); /** The configuration of startup checks. */ public volatile Map> startup_checks = new HashMap<>(); - public volatile DurationSpec repair_state_expires = DurationSpec.inDays(3); + public volatile DurationSpec.LongNanosecondsBound repair_state_expires = new DurationSpec.LongNanosecondsBound("3d"); public volatile int repair_state_size = 100_000; /** @@ -950,7 +950,7 @@ public class Config * A safety margin when purging paxos state information that has been safely replicated to a quorum. * Data for transactions initiated within this grace period will not be expunged. */ - public volatile DurationSpec paxos_purge_grace_period = new SmallestDurationSeconds("60s"); + public volatile DurationSpec.LongSecondsBound paxos_purge_grace_period = new DurationSpec.LongSecondsBound("60s"); /** * A safety mechanism for detecting incorrect paxos state, that may be down either to a bug or incorrect usage of LWTs @@ -1034,7 +1034,7 @@ public class Config public volatile int max_top_size_partition_count = 10; public volatile int max_top_tombstone_partition_count = 10; - public volatile DataStorageSpec min_tracked_partition_size_bytes = DataStorageSpec.inMebibytes(1); + public volatile DataStorageSpec.LongBytesBound min_tracked_partition_size_bytes = new DataStorageSpec.LongBytesBound("1MiB"); public volatile long min_tracked_partition_tombstone_count = 5000; public volatile boolean top_partitions_enabled = true; diff --git a/src/java/org/apache/cassandra/config/Converters.java b/src/java/org/apache/cassandra/config/Converters.java index 5e5f15a699..ccfc87b4d5 100644 --- a/src/java/org/apache/cassandra/config/Converters.java +++ b/src/java/org/apache/cassandra/config/Converters.java @@ -18,6 +18,7 @@ package org.apache.cassandra.config; +import java.util.concurrent.TimeUnit; import java.util.function.Function; /** @@ -37,71 +38,71 @@ public enum Converters * able to still use the old name too. No units involved. */ IDENTITY(null, null, o -> o, o -> o), - MILLIS_DURATION_LONG(Long.class, SmallestDurationMilliseconds.class, - SmallestDurationMilliseconds::inMilliseconds, + MILLIS_DURATION_LONG(Long.class, DurationSpec.LongMillisecondsBound.class, + DurationSpec.LongMillisecondsBound::new, o -> o.toMilliseconds()), - MILLIS_DURATION_INT(Integer.class, SmallestDurationMilliseconds.class, - i -> SmallestDurationMilliseconds.inMilliseconds(i), - DurationSpec::toMillisecondsAsInt), - MILLIS_DURATION_DOUBLE(Double.class, SmallestDurationMilliseconds.class, - o -> Double.isNaN(o) ? SmallestDurationMilliseconds.inMilliseconds(0) : SmallestDurationMilliseconds.inDoubleMilliseconds(o), + MILLIS_DURATION_INT(Integer.class, DurationSpec.IntMillisecondsBound.class, + DurationSpec.IntMillisecondsBound::new, + DurationSpec.IntMillisecondsBound::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, SmallestDurationMilliseconds.class, - o -> o == -1 ? null : SmallestDurationMilliseconds.inMilliseconds(o), - o -> o == null ? -1 : o.toMillisecondsAsInt()), - SECONDS_DURATION(Integer.class, SmallestDurationSeconds.class, - i -> SmallestDurationSeconds.inSeconds(i), - DurationSpec::toSecondsAsInt), - NEGATIVE_SECONDS_DURATION(Integer.class, SmallestDurationSeconds.class, - o -> o < 0 ? SmallestDurationSeconds.inSeconds(0) : SmallestDurationSeconds.inSeconds(o), - DurationSpec::toSecondsAsInt), + 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, + DurationSpec.IntSecondsBound::toSeconds), + NEGATIVE_SECONDS_DURATION(Integer.class, DurationSpec.IntSecondsBound.class, + o -> o < 0 ? new DurationSpec.IntSecondsBound(0) : new DurationSpec.IntSecondsBound(o), + DurationSpec.IntSecondsBound::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, SmallestDurationSeconds.class, - SmallestDurationSeconds::inSecondsString, + SECONDS_CUSTOM_DURATION(String.class, DurationSpec.IntSecondsBound.class, + DurationSpec.IntSecondsBound::inSecondsString, o -> Long.toString(o.toSeconds())), - MINUTES_DURATION(Integer.class, SmallestDurationMinutes.class, - i -> SmallestDurationMinutes.inMinutes(i), - DurationSpec::toMinutesAsInt), - MEBIBYTES_DATA_STORAGE_LONG(Long.class, SmallestDataStorageMebibytes.class, - SmallestDataStorageMebibytes::inMebibytes, - DataStorageSpec::toMebibytes), - MEBIBYTES_DATA_STORAGE_INT(Integer.class, SmallestDataStorageMebibytes.class, - i -> SmallestDataStorageMebibytes.inMebibytes(i), - DataStorageSpec::toMebibytesAsInt), - KIBIBYTES_DATASTORAGE(Integer.class, SmallestDataStorageKibibytes.class, - i -> SmallestDataStorageKibibytes.inKibibytes(i), - DataStorageSpec::toKibibytesAsInt), - BYTES_DATASTORAGE(Integer.class, DataStorageSpec.class, - i -> DataStorageSpec.inBytes(i), - DataStorageSpec::toBytesAsInt), + MINUTES_DURATION(Integer.class, DurationSpec.IntMinutesBound.class, + DurationSpec.IntMinutesBound::new, + DurationSpec.IntMinutesBound::toMinutes), + MEBIBYTES_DATA_STORAGE_LONG(Long.class, DataStorageSpec.LongMebibytesBound.class, + DataStorageSpec.LongMebibytesBound::new, + DataStorageSpec.LongMebibytesBound::toMebibytes), + MEBIBYTES_DATA_STORAGE_INT(Integer.class, DataStorageSpec.IntMebibytesBound.class, + DataStorageSpec.IntMebibytesBound::new, + DataStorageSpec.IntMebibytesBound::toMebibytes), + KIBIBYTES_DATASTORAGE(Integer.class, DataStorageSpec.IntKibibytesBound.class, + DataStorageSpec.IntKibibytesBound::new, + DataStorageSpec.IntKibibytesBound::toKibibytes), + BYTES_DATASTORAGE(Integer.class, DataStorageSpec.IntBytesBound.class, + DataStorageSpec.IntBytesBound::new, + DataStorageSpec.IntBytesBound::toBytes), /** * 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.class, - o -> o == -1 ? null : DataStorageSpec.inBytes(o), - DataStorageSpec::toBytes), - MEBIBYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.class, - i -> DataRateSpec.inMebibytesPerSecond(i), - DataRateSpec::toMebibytesPerSecondAsInt), + BYTES_CUSTOM_DATASTORAGE(Long.class, DataStorageSpec.LongBytesBound.class, + o -> o == -1 ? null : new DataStorageSpec.LongBytesBound(o), + DataStorageSpec.LongBytesBound::toBytes), + MEBIBYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.IntMebibytesPerSecondBound.class, + DataRateSpec.IntMebibytesPerSecondBound::new, + DataRateSpec.IntMebibytesPerSecondBound::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 megatibs per second prior CASSANDRA-15234. */ - MEGABITS_TO_MEBIBYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.class, - i -> DataRateSpec.megabitsPerSecondInMebibytesPerSecond(i), - DataRateSpec::toMegabitsPerSecondAsInt); - + MEGABITS_TO_MEBIBYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.IntMebibytesPerSecondBound.class, + i -> DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(i), + DataRateSpec.IntMebibytesPerSecondBound::toMegabitsPerSecondAsInt); private final Class oldType; private final Class newType; private final Function convert; diff --git a/src/java/org/apache/cassandra/config/DataRateSpec.java b/src/java/org/apache/cassandra/config/DataRateSpec.java index 22b138fe03..34eac7465a 100644 --- a/src/java/org/apache/cassandra/config/DataRateSpec.java +++ b/src/java/org/apache/cassandra/config/DataRateSpec.java @@ -25,101 +25,90 @@ import java.util.stream.Collectors; import com.google.common.primitives.Ints; +import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.BYTES_PER_SECOND; +import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND; + /** * Represents a data rate type used for cassandra configuration. It supports the opportunity for the users to be able to * add units to the confiuration parameter value. (CASSANDRA-15234) */ -public final class DataRateSpec +public abstract class DataRateSpec { /** * The Regexp used to parse the rate provided as String in cassandra.yaml. */ - private static final Pattern BIT_RATE_UNITS_PATTERN = Pattern.compile("^(\\d+)(MiB/s|KiB/s|B/s)$"); + private static final Pattern UNITS_PATTERN = Pattern.compile("^(\\d+)(MiB/s|KiB/s|B/s)$"); private final double quantity; private final DataRateUnit unit; - public DataRateSpec(String value) + private DataRateSpec(String value) { //parse the string field value - Matcher matcher = BIT_RATE_UNITS_PATTERN.matcher(value); + Matcher matcher = UNITS_PATTERN.matcher(value); if (!matcher.find()) - throw new IllegalArgumentException("Invalid bit rate: " + value + " Accepted units: MiB/s, KiB/s, B/s where " + - "case matters and " + "only non-negative values are valid"); + throw new IllegalArgumentException("Invalid data rate: " + value + " Accepted units: MiB/s, KiB/s, B/s where " + + "case matters and " + "only non-negative values are valid"); - quantity = Long.parseLong(matcher.group(1)); + quantity = (double) Long.parseLong(matcher.group(1)); unit = DataRateUnit.fromSymbol(matcher.group(2)); } - DataRateSpec(double quantity, DataRateUnit unit) + private DataRateSpec(String value, DataRateUnit minUnit, long max) { - if (quantity < 0) - throw new IllegalArgumentException("Invalid bit rate: value must be non-negative"); + this(value); - if (quantity > Long.MAX_VALUE) - throw new NumberFormatException("Invalid bit rate: value must be between 0 and Long.MAX_VALUE = 9223372036854775807"); + validateQuantity(value, quantity(), unit(), minUnit, max); + } + private DataRateSpec(double quantity, DataRateUnit unit, DataRateUnit minUnit, long max) + { this.quantity = quantity; this.unit = unit; + + validateQuantity(quantity, unit, minUnit, max); } - /** - * Creates a {@code DataRateSpec} of the specified amount of bits per second. - * - * @param bytesPerSecond the amount of bytes per second - * @return a {@code DataRateSpec} - */ - public static DataRateSpec inBytesPerSecond(long bytesPerSecond) + private static void validateQuantity(String value, double quantity, DataRateUnit unit, DataRateUnit minUnit, long max) { - return new DataRateSpec(bytesPerSecond, DataRateUnit.BYTES_PER_SECOND); + // negatives are not allowed by the regex pattern + if (minUnit.convert(quantity, unit) >= max) + throw new IllegalArgumentException("Invalid data rate: " + value + ". It shouldn't be more than " + + (max - 1) + " in " + minUnit.name().toLowerCase()); } - /** - * Creates a {@code DataRateSpec} of the specified amount of kibibytes per second. - * - * @param kibibytesPerSecond the amount of kibibytes per second - * @return a {@code DataRateSpec} - */ - public static DataRateSpec inKibibytesPerSecond(long kibibytesPerSecond) + private static void validateQuantity(double quantity, DataRateUnit unit, DataRateUnit minUnit, long max) { - return new DataRateSpec(kibibytesPerSecond, DataRateUnit.KIBIBYTES_PER_SECOND); - } - - /** - * Creates a {@code DataRateSpec} of the specified amount of mebibytes per second. - * - * @param mebibytesPerSecond the amount of mebibytes per second - * @return a {@code DataRateSpec} - */ - public static DataRateSpec inMebibytesPerSecond(long mebibytesPerSecond) - { - return new DataRateSpec(mebibytesPerSecond, DataRateUnit.MEBIBYTES_PER_SECOND); - } - - /** - * Creates a {@code DataRateSpec} of the specified amount of mebibytes per second. - * - * @param megabitsPerSecond the amount of megabits per second - * @return a {@code DataRateSpec} - */ - public static DataRateSpec megabitsPerSecondInMebibytesPerSecond(long megabitsPerSecond) - { - final double MEBIBYTES_PER_MEGABIT = 0.119209289550781; - double mebibytesPerSecond = (double)megabitsPerSecond * MEBIBYTES_PER_MEGABIT; - - return new DataRateSpec(mebibytesPerSecond, DataRateUnit.MEBIBYTES_PER_SECOND); + if (quantity < 0) + throw new IllegalArgumentException("Invalid data rate: value must be non-negative"); + + if (minUnit.convert(quantity, unit) >= max) + throw new IllegalArgumentException(String.format("Invalid data rate: %s %s. It shouldn't be more than %d in %s", + quantity, unit.name().toLowerCase(), + max - 1, minUnit.name().toLowerCase())); } + // get vs no-get prefix is not consistent in the code base, but for classes involved with config parsing, it is + // imporant to be explicit about get/set as this changes how parsing is done; this class is a data-type, so is + // not nested, having get/set can confuse parsing thinking this is a nested type /** * @return the data rate unit assigned. */ - public DataRateUnit getUnit() + public DataRateUnit unit() { return unit; } + /** + * @return the data rate quantity. + */ + private double quantity() + { + return quantity; + } + /** * @return the data rate in bytes per second */ @@ -226,6 +215,99 @@ public final class DataRateSpec return Math.round(quantity) + unit.symbol; } + /** + * Represents a data rate used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in bytes per second. + * If the user sets a different unit, we still validate that converted to bytes per second the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongBytesPerSecondBound extends DataRateSpec + { + /** + * Creates a {@code DataRateSpec.LongBytesPerSecondBound} of the specified amount. + * + * @param value the data rate + */ + public LongBytesPerSecondBound(String value) + { + super(value, BYTES_PER_SECOND, Long.MAX_VALUE); + } + + /** + * Creates a {@code DataRateSpec.LongBytesPerSecondBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in bytes per second + * @param unit in which the provided quantity is + */ + public LongBytesPerSecondBound(double quantity, DataRateUnit unit) + { + super(quantity, unit, BYTES_PER_SECOND, Long.MAX_VALUE); + } + + /** + * Creates a {@code DataRateSpec.LongBytesPerSecondBound} of the specified amount in bytes per second. + * + * @param bytesPerSecond where bytesPerSecond shouldn't be bigger than Long.MAX_VALUE + */ + public LongBytesPerSecondBound(long bytesPerSecond) + { + this(bytesPerSecond, BYTES_PER_SECOND); + } + } + + /** + * Represents a data rate used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in mebibytes per second. + * If the user sets a different unit - we still validate that converted to mebibytes per second the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntMebibytesPerSecondBound extends DataRateSpec + { + /** + * Creates a {@code DataRateSpec.IntMebibytesPerSecondBound} of the specified amount with bound [0, Integer.MAX_VALUE) mebibytes per second. + * + * @param value the data rate + */ + public IntMebibytesPerSecondBound(String value) + { + super(value, MEBIBYTES_PER_SECOND, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DataRateSpec.IntMebibytesPerSecondBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in mebibytes per second + * @param unit in which the provided quantity is + */ + public IntMebibytesPerSecondBound(double quantity, DataRateUnit unit) + { + super(quantity, unit, MEBIBYTES_PER_SECOND, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DataRateSpec.IntMebibytesPerSecondBound} of the specified amount in mebibytes per second. + * + * @param mebibytesPerSecond where mebibytesPerSecond shouldn't be bigger than Long.MAX_VALUE-1 + */ + public IntMebibytesPerSecondBound(long mebibytesPerSecond) + { + this (mebibytesPerSecond, MEBIBYTES_PER_SECOND); + } + + // this one should be used only for backward compatibility for stream_throughput_outbound and inter_dc_stream_throughput_outbound + // which were in megabits per second in 4.0. Do not start using it for any new properties + public static IntMebibytesPerSecondBound megabitsPerSecondInMebibytesPerSecond(long megabitsPerSecond) + { + final double MEBIBYTES_PER_MEGABIT = 0.119209289550781; + double mebibytesPerSecond = (double) megabitsPerSecond * MEBIBYTES_PER_MEGABIT; + + if (megabitsPerSecond >= Integer.MAX_VALUE) + throw new IllegalArgumentException("Invalid data rate: " + megabitsPerSecond + " megabits per second; " + + "stream_throughput_outbound and inter_dc_stream_throughput_outbound" + + " should be between 0 and " + Integer.MAX_VALUE + " in megabits per second"); + + return new IntMebibytesPerSecondBound(mebibytesPerSecond, MEBIBYTES_PER_SECOND); + } + } + public enum DataRateUnit { BYTES_PER_SECOND("B/s") @@ -245,7 +327,10 @@ public final class DataRateSpec return d / (1024.0 * 1024.0); } - public double toMegabitsPerSecond(double d) { return (d / 125000.0); } + public double toMegabitsPerSecond(double d) + { + return (d / 125000.0); + } public double convert(double source, DataRateUnit sourceUnit) { @@ -366,11 +451,14 @@ public final class DataRateSpec throw new AbstractMethodError(); } - public double toMegabitsPerSecond(double d) { throw new AbstractMethodError(); } + public double toMegabitsPerSecond(double d) + { + throw new AbstractMethodError(); + } public double convert(double source, DataRateUnit sourceUnit) { throw new AbstractMethodError(); } } -} \ No newline at end of file +} diff --git a/src/java/org/apache/cassandra/config/DataStorageSpec.java b/src/java/org/apache/cassandra/config/DataStorageSpec.java index 22e21f23a4..9a4348d633 100644 --- a/src/java/org/apache/cassandra/config/DataStorageSpec.java +++ b/src/java/org/apache/cassandra/config/DataStorageSpec.java @@ -23,11 +23,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.primitives.Ints; -import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.GIBIBYTES; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.BYTES; import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES; @@ -36,193 +34,104 @@ import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBY * users the opportunity to be able to provide config with a unit of their choice in cassandra.yaml as per the available * options. (CASSANDRA-15234) */ -public class DataStorageSpec +public abstract class DataStorageSpec { - /** - * Immutable map that matches supported time units according to a provided smallest supported time unit - */ - private static final ImmutableMap> MAP_UNITS_PER_MIN_UNIT = - ImmutableMap.of(KIBIBYTES, ImmutableSet.of(KIBIBYTES, MEBIBYTES, GIBIBYTES), - MEBIBYTES, ImmutableSet.of(MEBIBYTES, GIBIBYTES)); /** * The Regexp used to parse the storage provided as String. */ - private static final Pattern STORAGE_UNITS_PATTERN = Pattern.compile("^(\\d+)(GiB|MiB|KiB|B)$"); + private static final Pattern UNITS_PATTERN = Pattern.compile("^(\\d+)(GiB|MiB|KiB|B)$"); private final long quantity; private final DataStorageUnit unit; - public DataStorageSpec(String value) + private DataStorageSpec(long quantity, DataStorageUnit unit, DataStorageUnit minUnit, long max, String value) { - //parse the string field value - Matcher matcher = STORAGE_UNITS_PATTERN.matcher(value); - - if (!matcher.find()) - { - throw new IllegalArgumentException("Invalid data storage: " + value + " Accepted units: B, KiB, MiB, GiB" + - " where case matters and only non-negative values are accepted"); - } - - quantity = Long.parseLong(matcher.group(1)); - unit = DataStorageUnit.fromSymbol(matcher.group(2)); - } - - DataStorageSpec(long quantity, DataStorageUnit unit) - { - if (quantity < 0) - throw new IllegalArgumentException("Invalid data storage: value must be positive, but was " + quantity); - this.quantity = quantity; this.unit = unit; + + validateMinUnit(unit, minUnit, value); + validateQuantity(quantity, unit, minUnit, max); } - public DataStorageSpec (String value, DataStorageUnit minUnit) + private DataStorageSpec(String value, DataStorageUnit minUnit) { - if (!MAP_UNITS_PER_MIN_UNIT.containsKey(minUnit)) - throw new IllegalArgumentException("Invalid smallest unit set for " + value); - //parse the string field value - Matcher matcher = STORAGE_UNITS_PATTERN.matcher(value); + Matcher matcher = UNITS_PATTERN.matcher(value); if (matcher.find()) { quantity = Long.parseLong(matcher.group(1)); unit = DataStorageUnit.fromSymbol(matcher.group(2)); - if (!MAP_UNITS_PER_MIN_UNIT.get(minUnit).contains(unit)) - throw new IllegalArgumentException("Invalid data storage: " + value + " Accepted units:" + MAP_UNITS_PER_MIN_UNIT); + // this constructor is used only by extended classes for min unit; upper bound and min unit are guarded there accordingly } else { - throw new IllegalArgumentException("Invalid data storage: " + value + " Accepted units:" + MAP_UNITS_PER_MIN_UNIT.get(minUnit) + - " where case matters and only non-negative values are accepted"); + throw new IllegalArgumentException("Invalid data storage: " + value + " Accepted units:" + acceptedUnits(minUnit) + + " where case matters and only non-negative values are accepted"); } } - /** - * Creates a {@code DataStorageSpec} of the specified amount of bytes. - * - * @param bytes the amount of bytes - * @return a {@code DataStorageSpec} - */ - public static DataStorageSpec inBytes(long bytes) + + private DataStorageSpec(String value, DataStorageUnit minUnit, long max) { - return new DataStorageSpec(bytes, DataStorageUnit.BYTES); + this(value, minUnit); + + validateMinUnit(unit, minUnit, value); + validateQuantity(value, quantity(), unit(), minUnit, max); } - /** - * Creates a {@code DataStorageSpec} of the specified amount of kibibytes. - * - * @param kibibytes the amount of kibibytes - * @return a {@code DataStorageSpec} - */ - public static DataStorageSpec inKibibytes(long kibibytes) + private static void validateMinUnit(DataStorageUnit sourceUnit, DataStorageUnit minUnit, String value) { - return new DataStorageSpec(kibibytes, KIBIBYTES); + if (sourceUnit.compareTo(minUnit) < 0) + throw new IllegalArgumentException(String.format("Invalid data storage: %s Accepted units:%s", value, acceptedUnits(minUnit))); } - /** - * Creates a {@code DataStorageSpec} of the specified amount of mebibytes. - * - * @param mebibytes the amount of mebibytes - * @return a {@code DataStorageSpec} - */ - public static DataStorageSpec inMebibytes(long mebibytes) + private static String acceptedUnits(DataStorageUnit minUnit) { - return new DataStorageSpec(mebibytes, MEBIBYTES); + DataStorageUnit[] units = DataStorageUnit.values(); + return Arrays.toString(Arrays.copyOfRange(units, minUnit.ordinal(), units.length)); } - /** - * Creates a {@code DataStorageSpec} of the specified amount of gibibytes. - * - * @param gibibytes the amount of gibibytes - * @return a {@code DataStorageSpec} - */ - public static DataStorageSpec inGibibytes(long gibibytes) + private static void validateQuantity(String value, long quantity, DataStorageUnit sourceUnit, DataStorageUnit minUnit, long max) { - return new DataStorageSpec(gibibytes, GIBIBYTES); + // no need to validate for negatives as they are not allowed at first place from the regex + + if (minUnit.convert(quantity, sourceUnit) >= max) + throw new IllegalArgumentException("Invalid data storage: " + value + ". It shouldn't be more than " + + (max - 1) + " in " + minUnit.name().toLowerCase()); + } + + private static void validateQuantity(long quantity, DataStorageUnit sourceUnit, DataStorageUnit minUnit, long max) + { + if (quantity < 0) + throw new IllegalArgumentException("Invalid data storage: value must be non-negative"); + + if (minUnit.convert(quantity, sourceUnit) >= max) + throw new IllegalArgumentException(String.format("Invalid data storage: %d %s. It shouldn't be more than %d in %s", + quantity, sourceUnit.name().toLowerCase(), + max - 1, minUnit.name().toLowerCase())); + } + + // get vs no-get prefix is not consistent in the code base, but for classes involved with config parsing, it is + // imporant to be explicit about get/set as this changes how parsing is done; this class is a data-type, so is + // not nested, having get/set can confuse parsing thinking this is a nested type + /** + * @return the data storage quantity. + */ + public long quantity() + { + return quantity; } /** * @return the data storage unit. */ - public DataStorageUnit getUnit() + public DataStorageUnit unit() { return unit; } - /** - * @return the amount of data storage in bytes - */ - public long toBytes() - { - return unit.toBytes(quantity); - } - - /** - * Returns the amount of data storage in bytes as an {@code int} - * - * @return the amount of data storage in bytes or {@code Integer.MAX_VALUE} if the number of bytes is too large. - */ - public int toBytesAsInt() - { - return Ints.saturatedCast(toBytes()); - } - - /** - * @return the amount of data storage in kibibytes - */ - public long toKibibytes() - { - return unit.toKibibytes(quantity); - } - - /** - * Returns the amount of data storage in kibibytes as an {@code int} - * - * @return the amount of data storage in kibibytes or {@code Integer.MAX_VALUE} if the number of kibibytes is too large. - */ - public int toKibibytesAsInt() - { - return Ints.saturatedCast(toKibibytes()); - } - - /** - * @return the amount of data storage in mebibytes - */ - public long toMebibytes() - { - return unit.toMebibytes(quantity); - } - - /** - * Returns the amount of data storage in mebibytes as an {@code int} - * - * @return the amount of data storage in mebibytes or {@code Integer.MAX_VALUE} if the number of mebibytes is too large. - */ - public int toMebibytesAsInt() - { - return Ints.saturatedCast(toMebibytes()); - } - - /** - * @return the amount of data storage in gibibytes - */ - public long toGibibytes() - { - return unit.toGibibytes(quantity); - } - - /** - * Returns the amount of data storage in gibibytes as an {@code int} - * - * @return the amount of data storage in gibibytes or {@code Integer.MAX_VALUE} if the number of gibibytes is too large. - */ - public int toGibibytesAsInt() - { - return Ints.saturatedCast(toGibibytes()); - } - @Override public int hashCode() { @@ -253,6 +162,293 @@ public class DataStorageSpec return quantity + unit.symbol; } + /** + * Represents a data storage quantity used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in bytes. + * If the user sets a different unit - we still validate that converted to bytes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongBytesBound extends DataStorageSpec + { + /** + * Creates a {@code DataStorageSpec.LongBytesBound} of the specified amount. + * + * @param value the data storage + */ + public LongBytesBound(String value) + { + super(value, BYTES, Long.MAX_VALUE); + } + + /** + * Creates a {@code DataStorageSpec.LongBytesBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in bytes + * @param unit in which the provided quantity is + */ + public LongBytesBound(long quantity, DataStorageUnit unit) + { + super(quantity, unit, BYTES, Long.MAX_VALUE, quantity + unit.symbol); + } + + /** + * Creates a {@code DataStorageSpec.LongBytesBound} of the specified amount in bytes. + * + * @param bytes where bytes shouldn't be bigger than Long.MAX_VALUE-1 + */ + public LongBytesBound(long bytes) + { + this(bytes, BYTES); + } + + /** + * @return the amount of data storage in bytes + */ + public long toBytes() + { + return unit().toBytes(quantity()); + } + } + + /** + * Represents a data storage quantity used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in bytes. + * If the user sets a different unit - we still validate that converted to bytes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntBytesBound extends DataStorageSpec + { + /** + * Creates a {@code DataStorageSpec.IntBytesBound} of the specified amount. + * + * @param value the data storage + */ + public IntBytesBound(String value) + { + super(value, BYTES, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DataStorageSpec.IntBytesBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in bytes + * @param unit in which the provided quantity is + */ + public IntBytesBound(long quantity, DataStorageUnit unit) + { + super(quantity, unit, BYTES, Integer.MAX_VALUE, quantity + unit.symbol); + } + + /** + * Creates a {@code DataStorageSpec.IntBytesBound} of the specified amount in bytes. + * + * @param bytes where bytes shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntBytesBound(long bytes) + { + this(bytes, BYTES); + } + + /** + * Returns the amount of data storage in bytes as an {@code int} + * + * @return the amount of data storage in bytes or {@code Integer.MAX_VALUE} if the number of bytes is too large. + */ + public int toBytes() + { + return Ints.saturatedCast(unit().toBytes(quantity())); + } + } + + /** + * Represents a data storage quantity used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in kibibytes. + * If the user sets a different unit - we still validate that converted to kibibytes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntKibibytesBound extends DataStorageSpec + { + /** + * Creates a {@code DataStorageSpec.IntKibibytesBound} of the specified amount. + * + * @param value the data storage + */ + public IntKibibytesBound(String value) + { + super(value, KIBIBYTES, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DataStorageSpec.IntKibibytesBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in kibibytes + * @param unit in which the provided quantity is + */ + public IntKibibytesBound(long quantity, DataStorageUnit unit) + { + super(quantity, unit, KIBIBYTES, Integer.MAX_VALUE, quantity + unit.symbol); + } + + /** + * Creates a {@code DataStorageSpec.IntKibibytesBound} of the specified amount in kibibytes. + * + * @param kibibytes where kibibytes shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntKibibytesBound(long kibibytes) + { + this(kibibytes, KIBIBYTES); + } + + /** + * Returns the amount of data storage in bytes as an {@code int} + * + * @return the amount of data storage in bytes or {@code Integer.MAX_VALUE} if the number of bytes is too large. + */ + public int toBytes() + { + return Ints.saturatedCast(unit().toBytes(quantity())); + } + + /** + * Returns the amount of data storage in kibibytes as an {@code int} + * + * @return the amount of data storage in kibibytes or {@code Integer.MAX_VALUE} if the number of kibibytes is too large. + */ + public int toKibibytes() + { + return Ints.saturatedCast(unit().toKibibytes(quantity())); + } + } + + /** + * Represents a data storage quantity used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in mebibytes. + * If the user sets a different unit - we still validate that converted to mebibytes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongMebibytesBound extends DataStorageSpec + { + /** + * Creates a {@code DataStorageSpec.LongMebibytesBound} of the specified amount. + * + * @param value the data storage + */ + public LongMebibytesBound(String value) + { + super(value, MEBIBYTES, Long.MAX_VALUE); + } + + /** + * Creates a {@code DataStorageSpec.LongMebibytesBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in mebibytes + * @param unit in which the provided quantity is + */ + public LongMebibytesBound(long quantity, DataStorageUnit unit) + { + super(quantity, unit, MEBIBYTES, Long.MAX_VALUE, quantity + unit.symbol); + } + + /** + * Creates a {@code DataStorageSpec.LongMebibytesBound} of the specified amount in mebibytes. + * + * @param mebibytes where mebibytes shouldn't be bigger than Long.MAX_VALUE-1 + */ + public LongMebibytesBound(long mebibytes) + { + this(mebibytes, MEBIBYTES); + } + + /** + * @return the amount of data storage in bytes + */ + public long toBytes() + { + return unit().toBytes(quantity()); + } + + /** + * @return the amount of data storage in kibibytes + */ + public long toKibibytes() + { + return unit().toKibibytes(quantity()); + } + + /** + * @return the amount of data storage in mebibytes + */ + public long toMebibytes() + { + return unit().toMebibytes(quantity()); + } + } + + /** + * Represents a data storage quantity used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in mebibytes. + * If the user sets a different unit - we still validate that converted to mebibytes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntMebibytesBound extends DataStorageSpec + { + /** + * Creates a {@code DataStorageSpec.IntMebibytesBound} of the specified amount. + * + * @param value the data storage + */ + public IntMebibytesBound(String value) + { + super(value, MEBIBYTES, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DataStorageSpec.IntMebibytesBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in mebibytes + * @param unit in which the provided quantity is + */ + public IntMebibytesBound(long quantity, DataStorageUnit unit) + { + super(quantity, unit, MEBIBYTES, Integer.MAX_VALUE, quantity + unit.symbol); + } + + /** + * Creates a {@code DataStorageSpec.IntMebibytesBound} of the specified amount in mebibytes. + * + * @param mebibytes where mebibytes shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntMebibytesBound(long mebibytes) + { + this(mebibytes, MEBIBYTES); + } + + /** + * Returns the amount of data storage in bytes as an {@code int} + * + * @return the amount of data storage in bytes or {@code Integer.MAX_VALUE} if the number of bytes is too large. + */ + public int toBytes() + { + return Ints.saturatedCast(unit().toBytes(quantity())); + } + + /** + * Returns the amount of data storage in kibibytes as an {@code int} + * + * @return the amount of data storage in kibibytes or {@code Integer.MAX_VALUE} if the number of kibibytes is too large. + */ + public int toKibibytes() + { + return Ints.saturatedCast(unit().toKibibytes(quantity())); + } + + /** + * Returns the amount of data storage in mebibytes as an {@code int} + * + * @return the amount of data storage in mebibytes or {@code Integer.MAX_VALUE} if the number of mebibytes is too large. + */ + public int toMebibytes() + { + return Ints.saturatedCast(unit().toMebibytes(quantity())); + } + } + public enum DataStorageUnit { BYTES("B") diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index a636850534..16b5c4b78d 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -93,6 +93,7 @@ import org.apache.cassandra.utils.FBUtilities; import static org.apache.cassandra.config.CassandraRelevantProperties.OS_ARCH; import static org.apache.cassandra.config.CassandraRelevantProperties.SUN_ARCH_DATA_MODEL; import static org.apache.cassandra.config.CassandraRelevantProperties.TEST_JVM_DTEST_DISABLE_SSL; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES; import static org.apache.cassandra.io.util.FileUtils.ONE_GIB; import static org.apache.cassandra.io.util.FileUtils.ONE_MIB; import static org.apache.cassandra.utils.Clock.Global.logInitializationOutcome; @@ -119,7 +120,7 @@ public class DatabaseDescriptor /** * Request timeouts can not be less than below defined value (see CASSANDRA-9375) */ - static final SmallestDurationMilliseconds LOWEST_ACCEPTED_TIMEOUT = SmallestDurationMilliseconds.inMilliseconds(10L); + static final DurationSpec.LongMillisecondsBound LOWEST_ACCEPTED_TIMEOUT = new DurationSpec.LongMillisecondsBound(10L); private static Supplier newFailureDetector; private static IEndpointSnitch snitch; @@ -162,7 +163,7 @@ public class DatabaseDescriptor private static boolean daemonInitialized; private static final int searchConcurrencyFactor = Integer.parseInt(System.getProperty(Config.PROPERTY_PREFIX + "search_concurrency_factor", "1")); - private static DurationSpec autoSnapshoTtl; + private static DurationSpec.IntSecondsBound autoSnapshoTtl; private static volatile boolean disableSTCSInL0 = Boolean.getBoolean(Config.PROPERTY_PREFIX + "disable_stcs_in_l0"); private static final boolean unsafeSystem = Boolean.getBoolean(Config.PROPERTY_PREFIX + "unsafesystem"); @@ -397,11 +398,22 @@ public class DatabaseDescriptor //InetAddressAndPort and get the right defaults InetAddressAndPort.initializeDefaultPort(getStoragePort()); + // below 2 checks are needed in order to match the pre-CASSANDRA-15234 upper bound for those parameters which were still in megabits per second + if (conf.stream_throughput_outbound.toMegabitsPerSecond() >= Integer.MAX_VALUE) + { + throw new ConfigurationException("Invalid value of stream_throughput_outbound: " + conf.stream_throughput_outbound.toString(), false); + } + + if (conf.inter_dc_stream_throughput_outbound.toMegabitsPerSecond() >= Integer.MAX_VALUE) + { + throw new ConfigurationException("Invalid value of inter_dc_stream_throughput_outbound: " + conf.inter_dc_stream_throughput_outbound.toString(), false); + } + if (conf.auto_snapshot_ttl != null) { try { - autoSnapshoTtl = new DurationSpec(conf.auto_snapshot_ttl); + autoSnapshoTtl = new DurationSpec.IntSecondsBound(conf.auto_snapshot_ttl); } catch (IllegalArgumentException e) { @@ -490,24 +502,24 @@ public class DatabaseDescriptor logger.warn("concurrent_replicates has been deprecated and should be removed from cassandra.yaml"); if (conf.networking_cache_size == null) - conf.networking_cache_size = SmallestDataStorageMebibytes.inMebibytes(Math.min(128, (int) (Runtime.getRuntime().maxMemory() / (16 * 1048576)))); + conf.networking_cache_size = new DataStorageSpec.IntMebibytesBound(Math.min(128, (int) (Runtime.getRuntime().maxMemory() / (16 * 1048576)))); if (conf.file_cache_size == null) - conf.file_cache_size = SmallestDataStorageMebibytes.inMebibytes(Math.min(512, (int) (Runtime.getRuntime().maxMemory() / (4 * 1048576)))); + conf.file_cache_size = new DataStorageSpec.IntMebibytesBound(Math.min(512, (int) (Runtime.getRuntime().maxMemory() / (4 * 1048576)))); // round down for SSDs and round up for spinning disks if (conf.file_cache_round_up == null) conf.file_cache_round_up = conf.disk_optimization_strategy == Config.DiskOptimizationStrategy.spinning; if (conf.memtable_offheap_space == null) - conf.memtable_offheap_space = SmallestDataStorageMebibytes.inMebibytes( (int) (Runtime.getRuntime().maxMemory() / (4 * 1048576))); + conf.memtable_offheap_space = new DataStorageSpec.IntMebibytesBound((int) (Runtime.getRuntime().maxMemory() / (4 * 1048576))); // for the moment, we default to twice as much on-heap space as off-heap, as heap overhead is very large if (conf.memtable_heap_space == null) - conf.memtable_heap_space = SmallestDataStorageMebibytes.inMebibytes((int) (Runtime.getRuntime().maxMemory() / (4 * 1048576))); - if (conf.memtable_heap_space.toMebibytesAsInt() == 0) + conf.memtable_heap_space = new DataStorageSpec.IntMebibytesBound((int) (Runtime.getRuntime().maxMemory() / (4 * 1048576))); + if (conf.memtable_heap_space.toMebibytes() == 0) throw new ConfigurationException("memtable_heap_space must be positive, but was " + conf.memtable_heap_space, false); logger.info("Global memtable on-heap threshold is enabled at {}", conf.memtable_heap_space); - if (conf.memtable_offheap_space.toMebibytesAsInt() == 0) + if (conf.memtable_offheap_space.toMebibytes() == 0) logger.info("Global memtable off-heap threshold is disabled, HeapAllocator will be used instead"); else logger.info("Global memtable off-heap threshold is enabled at {}", conf.memtable_offheap_space); @@ -526,7 +538,7 @@ public class DatabaseDescriptor } if (conf.repair_session_space == null) - conf.repair_session_space = SmallestDataStorageMebibytes.inMebibytes(Math.max(1, (int) (Runtime.getRuntime().maxMemory() / (16 * 1048576)))); + conf.repair_session_space = new DataStorageSpec.IntMebibytesBound(Math.max(1, (int) (Runtime.getRuntime().maxMemory() / (16 * 1048576)))); if (conf.repair_session_space.toMebibytes() < 1) throw new ConfigurationException("repair_session_space must be > 0, but was " + conf.repair_session_space); @@ -536,12 +548,10 @@ public class DatabaseDescriptor checkForLowestAcceptedTimeouts(conf); long valueInBytes = conf.native_transport_max_frame_size.toBytes(); - if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE) + if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE-1) { - throw new ConfigurationException(String.format("%s must be positive value < %dB, but was %dB", - "native_transport_max_frame_size", - conf.native_transport_max_frame_size.getUnit() - .convert(Integer.MAX_VALUE, DataStorageSpec.DataStorageUnit.BYTES), + throw new ConfigurationException(String.format("native_transport_max_frame_size must be positive value < %dB, but was %dB", + Integer.MAX_VALUE, valueInBytes), false); } @@ -568,14 +578,14 @@ public class DatabaseDescriptor if (conf.native_transport_max_request_data_in_flight == null) { - conf.native_transport_max_request_data_in_flight = DataStorageSpec.inBytes(Runtime.getRuntime().maxMemory() / 10); + conf.native_transport_max_request_data_in_flight = new DataStorageSpec.LongBytesBound(Runtime.getRuntime().maxMemory() / 10); } if (conf.native_transport_max_request_data_in_flight_per_ip == null) { - conf.native_transport_max_request_data_in_flight_per_ip = DataStorageSpec.inBytes(Runtime.getRuntime().maxMemory() / 40); + conf.native_transport_max_request_data_in_flight_per_ip = new DataStorageSpec.LongBytesBound(Runtime.getRuntime().maxMemory() / 40); } - + if (conf.native_transport_rate_limiting_enabled) logger.info("Native transport rate-limiting enabled at {} requests/second.", conf.native_transport_max_requests_per_second); else @@ -591,7 +601,7 @@ public class DatabaseDescriptor "commitlog_total_space", preferredSizeInMiB, totalSpaceInBytes, 1, 4); - conf.commitlog_total_space = SmallestDataStorageMebibytes.inMebibytes(defaultSpaceInMiB); + conf.commitlog_total_space = new DataStorageSpec.IntMebibytesBound(defaultSpaceInMiB); } if (conf.cdc_enabled) @@ -611,7 +621,7 @@ public class DatabaseDescriptor "cdc_total_space", preferredSizeInMiB, totalSpaceInBytes, 1, 8); - conf.cdc_total_space = SmallestDataStorageMebibytes.inMebibytes(defaultSpaceInMiB); + conf.cdc_total_space = new DataStorageSpec.IntMebibytesBound(defaultSpaceInMiB); } logger.info("cdc_enabled is true. Starting casssandra node with Change-Data-Capture enabled."); @@ -803,7 +813,7 @@ public class DatabaseDescriptor + conf.commitlog_segment_size.toString(), false); if (conf.max_mutation_size == null) - conf.max_mutation_size = SmallestDataStorageKibibytes.inKibibytes(conf.commitlog_segment_size.toKibibytes() / 2); + conf.max_mutation_size = new DataStorageSpec.IntKibibytesBound(conf.commitlog_segment_size.toKibibytes() / 2); else if (conf.commitlog_segment_size.toKibibytes() < 2 * conf.max_mutation_size.toKibibytes()) throw new ConfigurationException("commitlog_segment_size must be at least twice the size of max_mutation_size / 1024", false); @@ -872,7 +882,7 @@ public class DatabaseDescriptor Math.min(conf.internode_application_receive_queue_reserve_endpoint_capacity.toBytes(), conf.internode_application_send_queue_reserve_endpoint_capacity.toBytes()); - conf.internode_max_message_size = DataStorageSpec.inBytes(maxMessageSizeInBytes); + conf.internode_max_message_size = new DataStorageSpec.IntBytesBound(maxMessageSizeInBytes); } validateMaxConcurrentAutoUpgradeTasksConf(conf.max_concurrent_automatic_sstable_upgrades); @@ -922,7 +932,7 @@ public class DatabaseDescriptor validateReadThresholds("row_index_read_size", config.row_index_read_size_warn_threshold, config.row_index_read_size_fail_threshold); } - private static void validateReadThresholds(String name, DataStorageSpec warn, DataStorageSpec fail) + private static void validateReadThresholds(String name, DataStorageSpec.LongBytesBound warn, DataStorageSpec.LongBytesBound fail) { if (fail != null && warn != null && fail.toBytes() < warn.toBytes()) throw new ConfigurationException(String.format("%s (%s) must be greater than or equal to %s (%s)", @@ -1135,49 +1145,49 @@ public class DatabaseDescriptor @VisibleForTesting static void checkForLowestAcceptedTimeouts(Config conf) { - if(conf.read_request_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.read_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("read_request_timeout", conf.read_request_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.read_request_timeout = new SmallestDurationMilliseconds("10ms"); + conf.read_request_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.range_request_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.range_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("range_request_timeout", conf.range_request_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.range_request_timeout = new SmallestDurationMilliseconds("10ms"); + conf.range_request_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.request_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("request_timeout", conf.request_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.request_timeout = new SmallestDurationMilliseconds("10ms"); + conf.request_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.write_request_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.write_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("write_request_timeout", conf.write_request_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.write_request_timeout = new SmallestDurationMilliseconds("10ms"); + conf.write_request_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.cas_contention_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.cas_contention_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("cas_contention_timeout", conf.cas_contention_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.cas_contention_timeout = new SmallestDurationMilliseconds("10ms"); + conf.cas_contention_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.counter_write_request_timeout.toMillisecondsAsInt()< LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.counter_write_request_timeout.toMilliseconds()< LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("counter_write_request_timeout", conf.counter_write_request_timeout, LOWEST_ACCEPTED_TIMEOUT); - conf.counter_write_request_timeout = new SmallestDurationMilliseconds("10ms"); + conf.counter_write_request_timeout = new DurationSpec.LongMillisecondsBound("10ms"); } - if(conf.truncate_request_timeout.toMillisecondsAsInt() < LOWEST_ACCEPTED_TIMEOUT.toMillisecondsAsInt()) + if(conf.truncate_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds()) { logInfo("truncate_request_timeout", conf.truncate_request_timeout, LOWEST_ACCEPTED_TIMEOUT); conf.truncate_request_timeout = LOWEST_ACCEPTED_TIMEOUT; } } - private static void logInfo(String property, SmallestDurationMilliseconds actualValue, SmallestDurationMilliseconds lowestAcceptedValue) + private static void logInfo(String property, DurationSpec.LongMillisecondsBound actualValue, DurationSpec.LongMillisecondsBound lowestAcceptedValue) { logger.info("found {}::{} less than lowest acceptable value {}, continuing with {}", property, @@ -1359,19 +1369,19 @@ public class DatabaseDescriptor public static int getPermissionsValidity() { - return conf.permissions_validity.toMillisecondsAsInt(); + return conf.permissions_validity.toMilliseconds(); } public static void setPermissionsValidity(int timeout) { - conf.permissions_validity = SmallestDurationMilliseconds.inMilliseconds(timeout); + conf.permissions_validity = new DurationSpec.IntMillisecondsBound(timeout); } public static int getPermissionsUpdateInterval() { return conf.permissions_update_interval == null - ? conf.permissions_validity.toMillisecondsAsInt() - : conf.permissions_update_interval.toMillisecondsAsInt(); + ? conf.permissions_validity.toMilliseconds() + : conf.permissions_update_interval.toMilliseconds(); } public static void setPermissionsUpdateInterval(int updateInterval) @@ -1379,7 +1389,7 @@ public class DatabaseDescriptor if (updateInterval == -1) conf.permissions_update_interval = null; else - conf.permissions_update_interval = SmallestDurationMilliseconds.inMilliseconds(updateInterval); + conf.permissions_update_interval = new DurationSpec.IntMillisecondsBound(updateInterval); } public static int getPermissionsCacheMaxEntries() @@ -1404,19 +1414,19 @@ public class DatabaseDescriptor public static int getRolesValidity() { - return conf.roles_validity.toMillisecondsAsInt(); + return conf.roles_validity.toMilliseconds(); } public static void setRolesValidity(int validity) { - conf.roles_validity = SmallestDurationMilliseconds.inMilliseconds(validity); + conf.roles_validity = new DurationSpec.IntMillisecondsBound(validity); } public static int getRolesUpdateInterval() { return conf.roles_update_interval == null - ? conf.roles_validity.toMillisecondsAsInt() - : conf.roles_update_interval.toMillisecondsAsInt(); + ? conf.roles_validity.toMilliseconds() + : conf.roles_update_interval.toMilliseconds(); } public static void setRolesCacheActiveUpdate(boolean update) @@ -1434,7 +1444,7 @@ public class DatabaseDescriptor if (interval == -1) conf.roles_update_interval = null; else - conf.roles_update_interval = SmallestDurationMilliseconds.inMilliseconds(interval); + conf.roles_update_interval = new DurationSpec.IntMillisecondsBound(interval); } public static int getRolesCacheMaxEntries() @@ -1449,19 +1459,19 @@ public class DatabaseDescriptor public static int getCredentialsValidity() { - return conf.credentials_validity.toMillisecondsAsInt(); + return conf.credentials_validity.toMilliseconds(); } public static void setCredentialsValidity(int timeout) { - conf.credentials_validity = SmallestDurationMilliseconds.inMilliseconds(timeout); + conf.credentials_validity = new DurationSpec.IntMillisecondsBound(timeout); } public static int getCredentialsUpdateInterval() { return conf.credentials_update_interval == null - ? conf.credentials_validity.toMillisecondsAsInt() - : conf.credentials_update_interval.toMillisecondsAsInt(); + ? conf.credentials_validity.toMilliseconds() + : conf.credentials_update_interval.toMilliseconds(); } public static void setCredentialsUpdateInterval(int updateInterval) @@ -1469,7 +1479,7 @@ public class DatabaseDescriptor if (updateInterval == -1) conf.credentials_update_interval = null; else - conf.credentials_update_interval = SmallestDurationMilliseconds.inMilliseconds(updateInterval); + conf.credentials_update_interval = new DurationSpec.IntMillisecondsBound(updateInterval); } public static int getCredentialsCacheMaxEntries() @@ -1494,12 +1504,13 @@ public class DatabaseDescriptor public static int getMaxValueSize() { - return conf.max_value_size.toBytesAsInt(); + return Ints.saturatedCast(conf.max_value_size.toMebibytes() * 1024L * 1024); } public static void setMaxValueSize(int maxValueSizeInBytes) { - conf.max_value_size = SmallestDataStorageMebibytes.inBytes(maxValueSizeInBytes); + // the below division is safe as this setter is used only in tests with values that won't lead to precision loss + conf.max_value_size = new DataStorageSpec.IntMebibytesBound((maxValueSizeInBytes / (1024L * 1024)), MEBIBYTES); } /** @@ -1586,56 +1597,56 @@ public class DatabaseDescriptor public static int getColumnIndexSize() { - return conf.column_index_size.toBytesAsInt(); + return conf.column_index_size.toBytes(); } public static int getColumnIndexSizeInKiB() { - return conf.column_index_size.toKibibytesAsInt(); + return conf.column_index_size.toKibibytes(); } public static void setColumnIndexSize(int val) { - SmallestDataStorageKibibytes memory = SmallestDataStorageKibibytes.inKibibytes(val); + DataStorageSpec.IntKibibytesBound memory = new DataStorageSpec.IntKibibytesBound(val); checkValidForByteConversion(memory, "column_index_size"); - conf.column_index_size = SmallestDataStorageKibibytes.inKibibytes(val); + conf.column_index_size = new DataStorageSpec.IntKibibytesBound(val); } public static int getColumnIndexCacheSize() { - return conf.column_index_cache_size.toBytesAsInt(); + return conf.column_index_cache_size.toBytes(); } public static int getColumnIndexCacheSizeInKiB() { - return conf.column_index_cache_size.toKibibytesAsInt(); + return conf.column_index_cache_size.toKibibytes(); } public static void setColumnIndexCacheSize(int val) { - SmallestDataStorageKibibytes memory = SmallestDataStorageKibibytes.inKibibytes(val); + DataStorageSpec.IntKibibytesBound memory = new DataStorageSpec.IntKibibytesBound(val); checkValidForByteConversion(memory, "column_index_cache_size"); - conf.column_index_cache_size = SmallestDataStorageKibibytes.inKibibytes(val); + conf.column_index_cache_size = new DataStorageSpec.IntKibibytesBound(val); } public static int getBatchSizeWarnThreshold() { - return conf.batch_size_warn_threshold.toBytesAsInt(); + return conf.batch_size_warn_threshold.toBytes(); } public static int getBatchSizeWarnThresholdInKiB() { - return conf.batch_size_warn_threshold.toKibibytesAsInt(); + return conf.batch_size_warn_threshold.toKibibytes(); } public static long getBatchSizeFailThreshold() { - return conf.batch_size_fail_threshold.toBytesAsInt(); + return conf.batch_size_fail_threshold.toBytes(); } public static int getBatchSizeFailThresholdInKiB() { - return conf.batch_size_fail_threshold.toKibibytesAsInt(); + return conf.batch_size_fail_threshold.toKibibytes(); } public static int getUnloggedBatchAcrossPartitionsWarnThreshold() @@ -1645,14 +1656,14 @@ public class DatabaseDescriptor public static void setBatchSizeWarnThresholdInKiB(int threshold) { - SmallestDataStorageKibibytes storage = SmallestDataStorageKibibytes.inKibibytes(threshold); + DataStorageSpec.IntKibibytesBound storage = new DataStorageSpec.IntKibibytesBound(threshold); checkValidForByteConversion(storage, "batch_size_warn_threshold"); - conf.batch_size_warn_threshold = SmallestDataStorageKibibytes.inKibibytes(threshold); + conf.batch_size_warn_threshold = new DataStorageSpec.IntKibibytesBound(threshold); } public static void setBatchSizeFailThresholdInKiB(int threshold) { - conf.batch_size_fail_threshold = SmallestDataStorageKibibytes.inKibibytes(threshold); + conf.batch_size_fail_threshold = new DataStorageSpec.IntKibibytesBound(threshold); } public static Collection getInitialTokens() @@ -1738,7 +1749,7 @@ public class DatabaseDescriptor public static void setNativeTransportIdleTimeout(long nativeTransportTimeout) { - conf.native_transport_idle_timeout= SmallestDurationMilliseconds.inMilliseconds(nativeTransportTimeout); + conf.native_transport_idle_timeout = new DurationSpec.LongMillisecondsBound(nativeTransportTimeout); } public static long getRpcTimeout(TimeUnit unit) @@ -1748,7 +1759,7 @@ public class DatabaseDescriptor public static void setRpcTimeout(long timeOutInMillis) { - conf.request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getReadRpcTimeout(TimeUnit unit) @@ -1758,7 +1769,7 @@ public class DatabaseDescriptor public static void setReadRpcTimeout(long timeOutInMillis) { - conf.read_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.read_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getRangeRpcTimeout(TimeUnit unit) @@ -1768,7 +1779,7 @@ public class DatabaseDescriptor public static void setRangeRpcTimeout(long timeOutInMillis) { - conf.range_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.range_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getWriteRpcTimeout(TimeUnit unit) @@ -1778,7 +1789,7 @@ public class DatabaseDescriptor public static void setWriteRpcTimeout(long timeOutInMillis) { - conf.write_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.write_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getCounterWriteRpcTimeout(TimeUnit unit) @@ -1788,7 +1799,7 @@ public class DatabaseDescriptor public static void setCounterWriteRpcTimeout(long timeOutInMillis) { - conf.counter_write_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.counter_write_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getCasContentionTimeout(TimeUnit unit) @@ -1798,7 +1809,7 @@ public class DatabaseDescriptor public static void setCasContentionTimeout(long timeOutInMillis) { - conf.cas_contention_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.cas_contention_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getTruncateRpcTimeout(TimeUnit unit) @@ -1808,7 +1819,7 @@ public class DatabaseDescriptor public static void setTruncateRpcTimeout(long timeOutInMillis) { - conf.truncate_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.truncate_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static long getRepairRpcTimeout(TimeUnit unit) @@ -1818,7 +1829,7 @@ public class DatabaseDescriptor public static void setRepairRpcTimeout(Long timeOutInMillis) { - conf.repair_request_timeout = SmallestDurationMilliseconds.inMilliseconds(timeOutInMillis); + conf.repair_request_timeout = new DurationSpec.LongMillisecondsBound(timeOutInMillis); } public static boolean hasCrossNodeTimeout() @@ -1952,7 +1963,7 @@ public class DatabaseDescriptor public static void setCompactionThroughputMebibytesPerSec(int value) { - conf.compaction_throughput = DataRateSpec.inMebibytesPerSecond(value); + conf.compaction_throughput = new DataRateSpec.IntMebibytesPerSecondBound(value); } public static long getCompactionLargePartitionWarningThreshold() { return conf.compaction_large_partition_warning_threshold.toBytes(); } @@ -2015,7 +2026,7 @@ public class DatabaseDescriptor public static void setStreamThroughputOutboundMegabitsPerSec(int value) { - conf.stream_throughput_outbound = DataRateSpec.megabitsPerSecondInMebibytesPerSecond(value); + conf.stream_throughput_outbound = DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(value); } public static int getEntireSSTableStreamThroughputOutboundMebibytesPerSecAsInt() @@ -2030,7 +2041,7 @@ public class DatabaseDescriptor public static void setEntireSSTableStreamThroughputOutboundMebibytesPerSec(int value) { - conf.entire_sstable_stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(value); + conf.entire_sstable_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(value); } public static int getInterDCStreamThroughputOutboundMegabitsPerSec() @@ -2045,7 +2056,7 @@ public class DatabaseDescriptor public static void setInterDCStreamThroughputOutboundMegabitsPerSec(int value) { - conf.inter_dc_stream_throughput_outbound = DataRateSpec.megabitsPerSecondInMebibytesPerSecond(value); + conf.inter_dc_stream_throughput_outbound = DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(value); } public static double getEntireSSTableInterDCStreamThroughputOutboundMebibytesPerSec() @@ -2060,7 +2071,7 @@ public class DatabaseDescriptor public static void setEntireSSTableInterDCStreamThroughputOutboundMebibytesPerSec(int value) { - conf.entire_sstable_inter_dc_stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(value); + conf.entire_sstable_inter_dc_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(value); } /** @@ -2162,7 +2173,7 @@ public class DatabaseDescriptor public static int getMaxMutationSize() { - return conf.max_mutation_size.toBytesAsInt(); + return conf.max_mutation_size.toBytes(); } public static int getTombstoneWarnThreshold() @@ -2210,7 +2221,7 @@ public class DatabaseDescriptor */ public static int getCommitLogSegmentSize() { - return conf.commitlog_segment_size.toBytesAsInt(); + return conf.commitlog_segment_size.toBytes(); } /** @@ -2222,7 +2233,7 @@ public class DatabaseDescriptor @VisibleForTesting /* Only for testing */ public static void setCommitLogSegmentSize(int sizeMebibytes) { - conf.commitlog_segment_size = SmallestDataStorageMebibytes.inMebibytes(sizeMebibytes); + conf.commitlog_segment_size = new DataStorageSpec.IntMebibytesBound(sizeMebibytes); } public static String getSavedCachesLocation() @@ -2327,83 +2338,83 @@ public class DatabaseDescriptor public static int getInternodeSocketSendBufferSizeInBytes() { - return conf.internode_socket_send_buffer_size.toBytesAsInt(); + return conf.internode_socket_send_buffer_size.toBytes(); } public static int getInternodeSocketReceiveBufferSizeInBytes() { - return conf.internode_socket_receive_buffer_size.toBytesAsInt(); + return conf.internode_socket_receive_buffer_size.toBytes(); } public static int getInternodeApplicationSendQueueCapacityInBytes() { - return conf.internode_application_send_queue_capacity.toBytesAsInt(); + return conf.internode_application_send_queue_capacity.toBytes(); } public static int getInternodeApplicationSendQueueReserveEndpointCapacityInBytes() { - return conf.internode_application_send_queue_reserve_endpoint_capacity.toBytesAsInt(); + return conf.internode_application_send_queue_reserve_endpoint_capacity.toBytes(); } public static int getInternodeApplicationSendQueueReserveGlobalCapacityInBytes() { - return conf.internode_application_send_queue_reserve_global_capacity.toBytesAsInt(); + return conf.internode_application_send_queue_reserve_global_capacity.toBytes(); } public static int getInternodeApplicationReceiveQueueCapacityInBytes() { - return conf.internode_application_receive_queue_capacity.toBytesAsInt(); + return conf.internode_application_receive_queue_capacity.toBytes(); } public static int getInternodeApplicationReceiveQueueReserveEndpointCapacityInBytes() { - return conf.internode_application_receive_queue_reserve_endpoint_capacity.toBytesAsInt(); + return conf.internode_application_receive_queue_reserve_endpoint_capacity.toBytes(); } public static int getInternodeApplicationReceiveQueueReserveGlobalCapacityInBytes() { - return conf.internode_application_receive_queue_reserve_global_capacity.toBytesAsInt(); + return conf.internode_application_receive_queue_reserve_global_capacity.toBytes(); } public static int getInternodeTcpConnectTimeoutInMS() { - return conf.internode_tcp_connect_timeout.toMillisecondsAsInt(); + return conf.internode_tcp_connect_timeout.toMilliseconds(); } public static void setInternodeTcpConnectTimeoutInMS(int value) { - conf.internode_tcp_connect_timeout = SmallestDurationMilliseconds.inMilliseconds(value); + conf.internode_tcp_connect_timeout = new DurationSpec.IntMillisecondsBound(value); } public static int getInternodeTcpUserTimeoutInMS() { - return conf.internode_tcp_user_timeout.toMillisecondsAsInt(); + return conf.internode_tcp_user_timeout.toMilliseconds(); } public static void setInternodeTcpUserTimeoutInMS(int value) { - conf.internode_tcp_user_timeout = SmallestDurationMilliseconds.inMilliseconds(value); + conf.internode_tcp_user_timeout = new DurationSpec.IntMillisecondsBound(value); } public static int getInternodeStreamingTcpUserTimeoutInMS() { - return conf.internode_streaming_tcp_user_timeout.toMillisecondsAsInt(); + return conf.internode_streaming_tcp_user_timeout.toMilliseconds(); } public static void setInternodeStreamingTcpUserTimeoutInMS(int value) { - conf.internode_streaming_tcp_user_timeout = SmallestDurationMilliseconds.inMilliseconds(value); + conf.internode_streaming_tcp_user_timeout = new DurationSpec.IntMillisecondsBound(value); } public static int getInternodeMaxMessageSizeInBytes() { - return conf.internode_max_message_size.toBytesAsInt(); + return conf.internode_max_message_size.toBytes(); } @VisibleForTesting public static void setInternodeMaxMessageSizeInBytes(int value) { - conf.internode_max_message_size = DataStorageSpec.inBytes(value); + conf.internode_max_message_size = new DataStorageSpec.IntBytesBound(value); } public static boolean startNativeTransport() @@ -2449,12 +2460,12 @@ public class DatabaseDescriptor public static int getNativeTransportMaxFrameSize() { - return conf.native_transport_max_frame_size.toBytesAsInt(); + return conf.native_transport_max_frame_size.toBytes(); } public static void setNativeTransportMaxFrameSize(int bytes) { - conf.native_transport_max_frame_size = SmallestDataStorageMebibytes.inMebibytes(bytes); + conf.native_transport_max_frame_size = new DataStorageSpec.IntMebibytesBound(bytes); } public static long getNativeTransportMaxConcurrentConnections() @@ -2499,17 +2510,17 @@ public class DatabaseDescriptor public static void setCommitLogSyncGroupWindow(long windowMillis) { - conf.commitlog_sync_group_window = SmallestDurationMilliseconds.inMilliseconds(windowMillis); + conf.commitlog_sync_group_window = new DurationSpec.IntMillisecondsBound(windowMillis); } public static int getNativeTransportReceiveQueueCapacityInBytes() { - return conf.native_transport_receive_queue_capacity.toBytesAsInt(); + return conf.native_transport_receive_queue_capacity.toBytes(); } public static void setNativeTransportReceiveQueueCapacityInBytes(int queueSize) { - conf.native_transport_receive_queue_capacity = DataStorageSpec.inBytes(queueSize); + conf.native_transport_receive_queue_capacity = new DataStorageSpec.IntBytesBound(queueSize); } public static long getNativeTransportMaxRequestDataInFlightPerIpInBytes() @@ -2582,9 +2593,9 @@ public class DatabaseDescriptor return conf.paxos_purge_grace_period.to(units); } - public static void setPaxosPurgeGrace(long value, TimeUnit units) + public static void setPaxosPurgeGrace(long seconds) { - conf.paxos_purge_grace_period = new DurationSpec(value, units); + conf.paxos_purge_grace_period = new DurationSpec.LongSecondsBound(seconds); } public static PaxosOnLinearizabilityViolation paxosOnLinearizabilityViolations() @@ -2642,8 +2653,7 @@ public class DatabaseDescriptor if (maxRequestDataInFlightInBytes == -1) maxRequestDataInFlightInBytes = Runtime.getRuntime().maxMemory() / 40; - conf.native_transport_max_request_data_in_flight_per_ip = DataStorageSpec.inBytes(maxRequestDataInFlightInBytes); - + conf.native_transport_max_request_data_in_flight_per_ip = new DataStorageSpec.LongBytesBound(maxRequestDataInFlightInBytes); } public static long getNativeTransportMaxRequestDataInFlightInBytes() @@ -2656,7 +2666,7 @@ public class DatabaseDescriptor if (maxRequestDataInFlightInBytes == -1) maxRequestDataInFlightInBytes = Runtime.getRuntime().maxMemory() / 10; - conf.native_transport_max_request_data_in_flight = DataStorageSpec.inBytes(maxRequestDataInFlightInBytes); + conf.native_transport_max_request_data_in_flight = new DataStorageSpec.LongBytesBound(maxRequestDataInFlightInBytes); } public static int getNativeTransportMaxRequestsPerSecond() @@ -2683,12 +2693,12 @@ public class DatabaseDescriptor public static int getCommitLogSyncPeriod() { - return conf.commitlog_sync_period.toMillisecondsAsInt(); + return conf.commitlog_sync_period.toMilliseconds(); } public static long getPeriodicCommitLogSyncBlock() { - SmallestDurationMilliseconds blockMillis = conf.periodic_commitlog_sync_lag_block; + DurationSpec.IntMillisecondsBound blockMillis = conf.periodic_commitlog_sync_lag_block; return blockMillis == null ? (long)(getCommitLogSyncPeriod() * 1.5) : blockMillis.toMilliseconds(); @@ -2696,7 +2706,7 @@ public class DatabaseDescriptor public static void setCommitLogSyncPeriod(int periodMillis) { - conf.commitlog_sync_period = SmallestDurationMilliseconds.inMilliseconds(periodMillis); + conf.commitlog_sync_period = new DurationSpec.IntMillisecondsBound(periodMillis); } public static Config.CommitLogSync getCommitLogSync() @@ -2763,13 +2773,13 @@ public class DatabaseDescriptor return conf.auto_snapshot; } - public static DurationSpec getAutoSnapshotTtl() + public static DurationSpec.IntSecondsBound getAutoSnapshotTtl() { return autoSnapshoTtl; } @VisibleForTesting - public static void setAutoSnapshotTtl(DurationSpec newTtl) + public static void setAutoSnapshotTtl(DurationSpec.IntSecondsBound newTtl) { autoSnapshoTtl = newTtl; } @@ -2845,22 +2855,23 @@ public class DatabaseDescriptor public static void setMaxHintWindow(int ms) { - conf.max_hint_window = SmallestDurationMilliseconds.inMilliseconds(ms); + conf.max_hint_window = new DurationSpec.IntMillisecondsBound(ms); } public static int getMaxHintWindow() { - return conf.max_hint_window.toMillisecondsAsInt(); + return conf.max_hint_window.toMilliseconds(); } public static void setMaxHintsSizePerHostInMiB(int value) { - conf.max_hints_size_per_host = DataStorageSpec.inMebibytes(value); + conf.max_hints_size_per_host = new DataStorageSpec.LongBytesBound(value, MEBIBYTES); } public static int getMaxHintsSizePerHostInMiB() { - return conf.max_hints_size_per_host.toMebibytesAsInt(); + // Warnings: this conversion rounds down while converting bytes to mebibytes + return Ints.saturatedCast(conf.max_hints_size_per_host.unit().toMebibytes(conf.max_hints_size_per_host.quantity())); } public static long getMaxHintsSizePerHost() @@ -2887,20 +2898,20 @@ public class DatabaseDescriptor public static int getDynamicUpdateInterval() { - return conf.dynamic_snitch_update_interval.toMillisecondsAsInt(); + return conf.dynamic_snitch_update_interval.toMilliseconds(); } public static void setDynamicUpdateInterval(int dynamicUpdateInterval) { - conf.dynamic_snitch_update_interval = SmallestDurationMilliseconds.inMilliseconds(dynamicUpdateInterval); + conf.dynamic_snitch_update_interval = new DurationSpec.IntMillisecondsBound(dynamicUpdateInterval); } public static int getDynamicResetInterval() { - return conf.dynamic_snitch_reset_interval.toMillisecondsAsInt(); + return conf.dynamic_snitch_reset_interval.toMilliseconds(); } public static void setDynamicResetInterval(int dynamicResetInterval) { - conf.dynamic_snitch_reset_interval = SmallestDurationMilliseconds.inMilliseconds(dynamicResetInterval); + conf.dynamic_snitch_reset_interval = new DurationSpec.IntMillisecondsBound(dynamicResetInterval); } public static double getDynamicBadnessThreshold() @@ -2936,22 +2947,22 @@ public class DatabaseDescriptor public static int getHintedHandoffThrottleInKiB() { - return conf.hinted_handoff_throttle.toKibibytesAsInt(); + return conf.hinted_handoff_throttle.toKibibytes(); } public static void setHintedHandoffThrottleInKiB(int throttleInKiB) { - conf.hinted_handoff_throttle = SmallestDataStorageKibibytes.inKibibytes(throttleInKiB); + conf.hinted_handoff_throttle = new DataStorageSpec.IntKibibytesBound(throttleInKiB); } public static int getBatchlogReplayThrottleInKiB() { - return conf.batchlog_replay_throttle.toKibibytesAsInt(); + return conf.batchlog_replay_throttle.toKibibytes(); } public static void setBatchlogReplayThrottleInKiB(int throttleInKiB) { - conf.batchlog_replay_throttle = SmallestDataStorageKibibytes.inKibibytes(throttleInKiB); + conf.batchlog_replay_throttle = new DataStorageSpec.IntKibibytesBound(throttleInKiB); } public static int getMaxHintsDeliveryThreads() @@ -2961,7 +2972,7 @@ public class DatabaseDescriptor public static int getHintsFlushPeriodInMS() { - return conf.hints_flush_period.toMillisecondsAsInt(); + return conf.hints_flush_period.toMilliseconds(); } public static long getMaxHintsFileSize() @@ -3013,7 +3024,7 @@ public class DatabaseDescriptor return 0; } - return conf.file_cache_size.toMebibytesAsInt(); + return conf.file_cache_size.toMebibytes(); } public static int getNetworkingCacheSizeInMiB() @@ -3024,7 +3035,7 @@ public class DatabaseDescriptor assert DatabaseDescriptor.isClientInitialized(); return 0; } - return conf.networking_cache_size.toMebibytesAsInt(); + return conf.networking_cache_size.toMebibytes(); } public static boolean getFileCacheRoundUp() @@ -3066,12 +3077,12 @@ public class DatabaseDescriptor public static int getSSTablePreemptiveOpenIntervalInMiB() { - return conf.sstable_preemptive_open_interval.toMebibytesAsInt(); + return conf.sstable_preemptive_open_interval.toMebibytes(); } public static void setSSTablePreemptiveOpenIntervalInMiB(int mib) { - conf.sstable_preemptive_open_interval = SmallestDataStorageMebibytes.inMebibytes(mib); + conf.sstable_preemptive_open_interval = new DataStorageSpec.IntMebibytesBound(mib); } public static boolean getTrickleFsync() @@ -3081,7 +3092,7 @@ public class DatabaseDescriptor public static int getTrickleFsyncIntervalInKiB() { - return conf.trickle_fsync_interval.toKibibytesAsInt(); + return conf.trickle_fsync_interval.toKibibytes(); } public static long getKeyCacheSizeInMiB() @@ -3096,12 +3107,12 @@ public class DatabaseDescriptor public static int getKeyCacheSavePeriod() { - return conf.key_cache_save_period.toSecondsAsInt(); + return conf.key_cache_save_period.toSeconds(); } public static void setKeyCacheSavePeriod(int keyCacheSavePeriod) { - conf.key_cache_save_period = SmallestDurationSeconds.inSeconds(keyCacheSavePeriod); + conf.key_cache_save_period = new DurationSpec.IntSecondsBound(keyCacheSavePeriod); } public static int getKeyCacheKeysToSave() @@ -3127,17 +3138,17 @@ public class DatabaseDescriptor @VisibleForTesting public static void setRowCacheSizeInMiB(long val) { - conf.row_cache_size = SmallestDataStorageMebibytes.inMebibytes(val); + conf.row_cache_size = new DataStorageSpec.LongMebibytesBound(val); } public static int getRowCacheSavePeriod() { - return conf.row_cache_save_period.toSecondsAsInt(); + return conf.row_cache_save_period.toSeconds(); } public static void setRowCacheSavePeriod(int rowCacheSavePeriod) { - conf.row_cache_save_period = SmallestDurationSeconds.inSeconds(rowCacheSavePeriod); + conf.row_cache_save_period = new DurationSpec.IntSecondsBound(rowCacheSavePeriod); } public static int getRowCacheKeysToSave() @@ -3162,23 +3173,23 @@ public class DatabaseDescriptor public static int getCounterCacheSavePeriod() { - return conf.counter_cache_save_period.toSecondsAsInt(); + return conf.counter_cache_save_period.toSeconds(); } public static void setCounterCacheSavePeriod(int counterCacheSavePeriod) { - conf.counter_cache_save_period = SmallestDurationSeconds.inSeconds(counterCacheSavePeriod); + conf.counter_cache_save_period = new DurationSpec.IntSecondsBound(counterCacheSavePeriod); } public static int getCacheLoadTimeout() { - return conf.cache_load_timeout.toSecondsAsInt(); + return conf.cache_load_timeout.toSeconds(); } @VisibleForTesting public static void setCacheLoadTimeout(int seconds) { - conf.cache_load_timeout = SmallestDurationSeconds.inSeconds(seconds); + conf.cache_load_timeout = new DurationSpec.IntSecondsBound(seconds); } public static int getCounterCacheKeysToSave() @@ -3193,7 +3204,7 @@ public class DatabaseDescriptor public static int getStreamingKeepAlivePeriod() { - return conf.streaming_keep_alive_period.toSecondsAsInt(); + return conf.streaming_keep_alive_period.toSeconds(); } public static int getStreamingConnectionsPerHost() @@ -3264,7 +3275,7 @@ public class DatabaseDescriptor public static int getRepairSessionSpaceInMiB() { - return conf.repair_session_space.toMebibytesAsInt(); + return conf.repair_session_space.toMebibytes(); } public static void setRepairSessionSpaceInMiB(int sizeInMiB) @@ -3276,7 +3287,7 @@ public class DatabaseDescriptor logger.warn("A repair_session_space of " + conf.repair_session_space + " is likely to cause heap pressure."); - conf.repair_session_space = SmallestDataStorageMebibytes.inMebibytes(sizeInMiB); + conf.repair_session_space = new DataStorageSpec.IntMebibytesBound(sizeInMiB); } public static int getPaxosRepairParallelism() @@ -3304,7 +3315,7 @@ public class DatabaseDescriptor public static int getIndexSummaryResizeIntervalInMinutes() { - return conf.index_summary_resize_interval.toMinutesAsInt(); + return conf.index_summary_resize_interval.toMinutes(); } public static boolean hasLargeAddressSpace() @@ -3325,12 +3336,12 @@ public class DatabaseDescriptor public static int getTracetypeRepairTTL() { - return conf.trace_type_repair_ttl.toSecondsAsInt(); + return conf.trace_type_repair_ttl.toSeconds(); } public static int getTracetypeQueryTTL() { - return conf.trace_type_query_ttl.toSecondsAsInt(); + return conf.trace_type_query_ttl.toSeconds(); } public static long getPreparedStatementsCacheSizeMiB() @@ -3365,7 +3376,7 @@ public class DatabaseDescriptor public static void setUserDefinedFunctionWarnTimeout(long userDefinedFunctionWarnTimeout) { - conf.user_defined_functions_warn_timeout = SmallestDurationMilliseconds.inMilliseconds(userDefinedFunctionWarnTimeout); + conf.user_defined_functions_warn_timeout = new DurationSpec.LongMillisecondsBound(userDefinedFunctionWarnTimeout); } public static boolean allowInsecureUDFs() @@ -3426,7 +3437,7 @@ public class DatabaseDescriptor public static void setUserDefinedFunctionFailTimeout(long userDefinedFunctionFailTimeout) { - conf.user_defined_functions_fail_timeout = SmallestDurationMilliseconds.inMilliseconds(userDefinedFunctionFailTimeout); + conf.user_defined_functions_fail_timeout = new DurationSpec.LongMillisecondsBound(userDefinedFunctionFailTimeout); } public static Config.UserFunctionTimeoutPolicy getUserFunctionTimeoutPolicy() @@ -3482,18 +3493,18 @@ public class DatabaseDescriptor public static int getCDCSpaceInMiB() { - return conf.cdc_total_space.toMebibytesAsInt(); + return conf.cdc_total_space.toMebibytes(); } @VisibleForTesting public static void setCDCSpaceInMiB(int input) { - conf.cdc_total_space = SmallestDataStorageMebibytes.inMebibytes(input); + conf.cdc_total_space = new DataStorageSpec.IntMebibytesBound(input); } public static int getCDCDiskCheckInterval() { - return conf.cdc_free_space_check_interval.toMillisecondsAsInt(); + return conf.cdc_free_space_check_interval.toMilliseconds(); } @VisibleForTesting @@ -3589,7 +3600,7 @@ public class DatabaseDescriptor if (value > getConcurrentCompactors()) logger.warn("max_concurrent_automatic_sstable_upgrades ({}) is larger than concurrent_compactors ({})", value, getConcurrentCompactors()); } - + public static AuditLogOptions getAuditLoggingOptions() { return conf.audit_logging_options; @@ -3689,14 +3700,14 @@ public class DatabaseDescriptor /** * Ensures passed in configuration value is positive and will not overflow when converted to Bytes */ - private static void checkValidForByteConversion(final SmallestDataStorageKibibytes value, String name) + private static void checkValidForByteConversion(final DataStorageSpec.IntKibibytesBound value, String name) { long valueInBytes = value.toBytes(); - if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE) + if (valueInBytes < 0 || valueInBytes > Integer.MAX_VALUE - 1) { throw new ConfigurationException(String.format("%s must be positive value <= %dB, but was %dB", name, - Integer.MAX_VALUE, + Integer.MAX_VALUE - 1, valueInBytes), false); } @@ -3704,7 +3715,7 @@ public class DatabaseDescriptor public static int getValidationPreviewPurgeHeadStartInSec() { - return conf.validation_preview_purge_head_start.toSecondsAsInt(); + return conf.validation_preview_purge_head_start.toSeconds(); } public static boolean checkForDuplicateRowsDuringReads() @@ -3895,7 +3906,7 @@ public class DatabaseDescriptor public static int getDenylistRefreshSeconds() { - return conf.denylist_refresh.toSecondsAsInt(); + return conf.denylist_refresh.toSeconds(); } public static void setDenylistRefreshSeconds(int seconds) @@ -3903,12 +3914,12 @@ public class DatabaseDescriptor if (seconds <= 0) throw new IllegalArgumentException("denylist_refresh must be a positive integer."); - conf.denylist_refresh = SmallestDurationSeconds.inSeconds(seconds); + conf.denylist_refresh = new DurationSpec.IntSecondsBound(seconds); } public static int getDenylistInitialLoadRetrySeconds() { - return conf.denylist_initial_load_retry.toSecondsAsInt(); + return conf.denylist_initial_load_retry.toSeconds(); } public static void setDenylistInitialLoadRetrySeconds(int seconds) @@ -3916,7 +3927,7 @@ public class DatabaseDescriptor if (seconds <= 0) throw new IllegalArgumentException("denylist_initial_load_retry must be a positive integer."); - conf.denylist_initial_load_retry = SmallestDurationSeconds.inSeconds(seconds); + conf.denylist_initial_load_retry = new DurationSpec.IntSecondsBound(seconds); } public static ConsistencyLevel getDenylistConsistencyLevel() @@ -3983,72 +3994,72 @@ public class DatabaseDescriptor } @Nullable - public static DataStorageSpec getCoordinatorReadSizeWarnThreshold() + public static DataStorageSpec.LongBytesBound getCoordinatorReadSizeWarnThreshold() { return conf.coordinator_read_size_warn_threshold; } - public static void setCoordinatorReadSizeWarnThreshold(@Nullable DataStorageSpec value) + public static void setCoordinatorReadSizeWarnThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating coordinator_read_size_warn_threshold to {}", value); conf.coordinator_read_size_warn_threshold = value; } @Nullable - public static DataStorageSpec getCoordinatorReadSizeFailThreshold() + public static DataStorageSpec.LongBytesBound getCoordinatorReadSizeFailThreshold() { return conf.coordinator_read_size_fail_threshold; } - public static void setCoordinatorReadSizeFailThreshold(@Nullable DataStorageSpec value) + public static void setCoordinatorReadSizeFailThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating coordinator_read_size_fail_threshold to {}", value); conf.coordinator_read_size_fail_threshold = value; } @Nullable - public static DataStorageSpec getLocalReadSizeWarnThreshold() + public static DataStorageSpec.LongBytesBound getLocalReadSizeWarnThreshold() { return conf.local_read_size_warn_threshold; } - public static void setLocalReadSizeWarnThreshold(@Nullable DataStorageSpec value) + public static void setLocalReadSizeWarnThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating local_read_size_warn_threshold to {}", value); conf.local_read_size_warn_threshold = value; } @Nullable - public static DataStorageSpec getLocalReadSizeFailThreshold() + public static DataStorageSpec.LongBytesBound getLocalReadSizeFailThreshold() { return conf.local_read_size_fail_threshold; } - public static void setLocalReadSizeFailThreshold(@Nullable DataStorageSpec value) + public static void setLocalReadSizeFailThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating local_read_size_fail_threshold to {}", value); conf.local_read_size_fail_threshold = value; } @Nullable - public static DataStorageSpec getRowIndexReadSizeWarnThreshold() + public static DataStorageSpec.LongBytesBound getRowIndexReadSizeWarnThreshold() { return conf.row_index_read_size_warn_threshold; } - public static void setRowIndexReadSizeWarnThreshold(@Nullable DataStorageSpec value) + public static void setRowIndexReadSizeWarnThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating row_index_size_warn_threshold to {}", value); conf.row_index_read_size_warn_threshold = value; } @Nullable - public static DataStorageSpec getRowIndexReadSizeFailThreshold() + public static DataStorageSpec.LongBytesBound getRowIndexReadSizeFailThreshold() { return conf.row_index_read_size_fail_threshold; } - public static void setRowIndexReadSizeFailThreshold(@Nullable DataStorageSpec value) + public static void setRowIndexReadSizeFailThreshold(@Nullable DataStorageSpec.LongBytesBound value) { logger.info("updating row_index_read_size_fail_threshold to {}", value); conf.row_index_read_size_fail_threshold = value; @@ -4100,12 +4111,12 @@ public class DatabaseDescriptor } } - public static DurationSpec getStreamingStateExpires() + public static DurationSpec.LongNanosecondsBound getStreamingStateExpires() { return conf.streaming_state_expires; } - public static void setStreamingStateExpires(DurationSpec duration) + public static void setStreamingStateExpires(DurationSpec.LongNanosecondsBound duration) { if (!conf.streaming_state_expires.equals(Objects.requireNonNull(duration, "duration"))) { @@ -4114,12 +4125,12 @@ public class DatabaseDescriptor } } - public static DataStorageSpec getStreamingStateSize() + public static DataStorageSpec.LongBytesBound getStreamingStateSize() { return conf.streaming_state_size; } - public static void setStreamingStateSize(DataStorageSpec duration) + public static void setStreamingStateSize(DataStorageSpec.LongBytesBound duration) { if (!conf.streaming_state_size.equals(Objects.requireNonNull(duration, "duration"))) { @@ -4133,12 +4144,12 @@ public class DatabaseDescriptor return conf.enable_uuid_sstable_identifiers; } - public static DurationSpec getRepairStateExpires() + public static DurationSpec.LongNanosecondsBound getRepairStateExpires() { return conf.repair_state_expires; } - public static void setRepairStateExpires(DurationSpec duration) + public static void setRepairStateExpires(DurationSpec.LongNanosecondsBound duration) { if (!conf.repair_state_expires.equals(Objects.requireNonNull(duration, "duration"))) { @@ -4186,12 +4197,12 @@ public class DatabaseDescriptor conf.max_top_tombstone_partition_count = value; } - public static DataStorageSpec getMinTrackedPartitionSize() + public static DataStorageSpec.LongBytesBound getMinTrackedPartitionSize() { return conf.min_tracked_partition_size_bytes; } - public static void setMinTrackedPartitionSize(DataStorageSpec spec) + public static void setMinTrackedPartitionSize(DataStorageSpec.LongBytesBound spec) { conf.min_tracked_partition_size_bytes = spec; } diff --git a/src/java/org/apache/cassandra/config/DurationSpec.java b/src/java/org/apache/cassandra/config/DurationSpec.java index f675110721..ba7e9f8415 100644 --- a/src/java/org/apache/cassandra/config/DurationSpec.java +++ b/src/java/org/apache/cassandra/config/DurationSpec.java @@ -24,14 +24,14 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.primitives.Ints; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; /** @@ -39,77 +39,87 @@ import static java.util.concurrent.TimeUnit.SECONDS; * users the opportunity to be able to provide config with a unit of their choice in cassandra.yaml as per the available * options. (CASSANDRA-15234) */ -public class DurationSpec +public abstract class DurationSpec { - /** - * Immutable map that matches supported time units according to a provided smallest supported time unit - */ - private static final ImmutableMap> MAP_UNITS_PER_MIN_UNIT = - ImmutableMap.of(MILLISECONDS, ImmutableSet.of(MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS), - SECONDS, ImmutableSet.of(SECONDS, MINUTES, HOURS, DAYS), - MINUTES, ImmutableSet.of(MINUTES, HOURS, DAYS)); /** * The Regexp used to parse the duration provided as String. */ - private static final Pattern TIME_UNITS_PATTERN = Pattern.compile(("^(\\d+)(d|h|s|ms|us|µs|ns|m)$")); - - private static final Pattern VALUES_PATTERN = Pattern.compile(("\\d+")); + private static final Pattern UNITS_PATTERN = Pattern.compile(("^(\\d+)(d|h|s|ms|us|µs|ns|m)$")); private final long quantity; private final TimeUnit unit; - public DurationSpec(String value) + private DurationSpec(long quantity, TimeUnit unit, TimeUnit minUnit, long max) { - //parse the string field value - Matcher matcher = TIME_UNITS_PATTERN.matcher(value); + this.quantity = quantity; + this.unit = unit; + + validateMinUnit(unit, minUnit, quantity + " " + unit); + validateQuantity(quantity, unit, minUnit, max); + } + + private DurationSpec(double quantity, TimeUnit unit, TimeUnit minUnit, long max) + { + this(Math.round(quantity), unit, minUnit, max); + } + + private DurationSpec(String value, TimeUnit minUnit) + { + Matcher matcher = UNITS_PATTERN.matcher(value); if (matcher.find()) { quantity = Long.parseLong(matcher.group(1)); unit = fromSymbol(matcher.group(2)); + + // this constructor is used only by extended classes for min unit; upper bound and min unit are guarded there accordingly } else { - throw new IllegalArgumentException("Invalid duration: " + value + " Accepted units: d, h, m, s, ms, us, µs," + - " ns where case matters and " + "only non-negative values"); + throw new IllegalArgumentException("Invalid duration: " + value + " Accepted units:" + acceptedUnits(minUnit) + + " where case matters and only non-negative values."); } } - DurationSpec(long quantity, TimeUnit unit) + private DurationSpec(String value, TimeUnit minUnit, long max) + { + this(value, minUnit); + + validateMinUnit(unit, minUnit, value); + validateQuantity(value, quantity(), unit(), minUnit, max); + } + + private static void validateMinUnit(TimeUnit unit, TimeUnit minUnit, String value) + { + if (unit.compareTo(minUnit) < 0) + throw new IllegalArgumentException(String.format("Invalid duration: %s Accepted units:%s", value, acceptedUnits(minUnit))); + } + + private static String acceptedUnits(TimeUnit minUnit) + { + TimeUnit[] units = TimeUnit.values(); + return Arrays.toString(Arrays.copyOfRange(units, minUnit.ordinal(), units.length)); + } + + private static void validateQuantity(String value, long quantity, TimeUnit sourceUnit, TimeUnit minUnit, long max) + { + // no need to validate for negatives as they are not allowed at first place from the regex + + if (minUnit.convert(quantity, sourceUnit) >= max) + throw new IllegalArgumentException("Invalid duration: " + value + ". It shouldn't be more than " + + (max - 1) + " in " + minUnit.name().toLowerCase()); + } + + private static void validateQuantity(long quantity, TimeUnit sourceUnit, TimeUnit minUnit, long max) { if (quantity < 0) - throw new IllegalArgumentException("Invalid duration " + quantity + ": value must be positive"); + throw new IllegalArgumentException("Invalid duration: value must be non-negative"); - this.quantity = quantity; - this.unit = unit; - } - - DurationSpec(double quantity, TimeUnit unit) - { - this(Math.round(quantity), unit); - } - - public DurationSpec(String value, TimeUnit minUnit) - { - if (!MAP_UNITS_PER_MIN_UNIT.containsKey(minUnit)) - throw new IllegalArgumentException("Invalid smallest unit set for " + value); - - Matcher matcher = TIME_UNITS_PATTERN.matcher(value); - - if(matcher.find()) - { - quantity = Long.parseLong(matcher.group(1)); - unit = fromSymbol(matcher.group(2)); - - if (!MAP_UNITS_PER_MIN_UNIT.get(minUnit).contains(unit)) - throw new IllegalArgumentException("Invalid duration: " + value + " Accepted units:" + MAP_UNITS_PER_MIN_UNIT.get(minUnit)); - } - else - { - throw new IllegalArgumentException("Invalid duration: " + value + " Accepted units:" + MAP_UNITS_PER_MIN_UNIT.get(minUnit) + - " where case matters and only non-negative values."); - } + if (minUnit.convert(quantity, sourceUnit) >= max) + throw new IllegalArgumentException(String.format("Invalid duration: %d %s. It shouldn't be more than %d in %s", + quantity, sourceUnit.name().toLowerCase(), + max - 1, minUnit.name().toLowerCase())); } // get vs no-get prefix is not consistent in the code base, but for classes involved with config parsing, it is @@ -125,91 +135,6 @@ public class DurationSpec return unit; } - /** - * Creates a {@code DurationSpec} of the specified amount of milliseconds. - * - * @param milliseconds the amount of milliseconds - * @return a duration - */ - public static DurationSpec inMilliseconds(long milliseconds) - { - return new DurationSpec(milliseconds, MILLISECONDS); - } - - public static DurationSpec inDoubleMilliseconds(double milliseconds) - { - return new DurationSpec(milliseconds, MILLISECONDS); - } - - /** - * Creates a {@code DurationSpec} of the specified amount of seconds. - * - * @param seconds the amount of seconds - * @return a duration - */ - public static DurationSpec inSeconds(long seconds) - { - return new DurationSpec(seconds, SECONDS); - } - - /** - * Creates a {@code DurationSpec} of the specified amount of minutes. - * - * @param minutes the amount of minutes - * @return a duration - */ - public static DurationSpec inMinutes(long minutes) - { - return new DurationSpec(minutes, MINUTES); - } - - /** - * Creates a {@code DurationSpec} of the specified amount of hours. - * - * @param hours the amount of hours - * @return a duration - */ - public static DurationSpec inHours(long hours) - { - return new DurationSpec(hours, HOURS); - } - - /** - * Creates a {@code DurationSpec} of the specified amount of days. - * - * @param days the amount of days - * @return a duration - */ - public static DurationSpec inDays(long days) - { - return new DurationSpec(days, DAYS); - } - - /** - * Creates a {@code DurationSpec} of the specified amount of seconds. Custom method for special cases. - * - * @param value which can be in the old form only presenting the quantity or the post CASSANDRA-15234 form - a - * value consisting of quantity and unit. This method is necessary for three parameters which didn't change their - * names but only their value format. (key_cache_save_period, row_cache_save_period, counter_cache_save_period) - * @return a duration - */ - public static DurationSpec inSecondsString(String value) - { - //parse the string field value - Matcher matcher = VALUES_PATTERN.matcher(value); - - long seconds; - //if the provided string value is just a number, then we create a Duration Spec value in seconds - if (matcher.matches()) - { - seconds = Long.parseLong(value); - return new DurationSpec(seconds, SECONDS); - } - - //otherwise we just use the standard constructors - return new DurationSpec(value); - } - /** * @param symbol the time unit symbol * @return the time unit associated to the specified symbol @@ -224,12 +149,12 @@ public class DurationSpec case "s": return SECONDS; case "ms": return MILLISECONDS; case "us": - case "µs": return TimeUnit.MICROSECONDS; + case "µs": return MICROSECONDS; case "ns": return TimeUnit.NANOSECONDS; } throw new IllegalArgumentException(String.format("Unsupported time unit: %s. Supported units are: %s", symbol, Arrays.stream(TimeUnit.values()) - .map(DurationSpec::getSymbol) + .map(DurationSpec::symbol) .collect(Collectors.joining(", ")))); } @@ -242,104 +167,6 @@ public class DurationSpec return targetUnit.convert(quantity, unit); } - /** - * @return this duration in number of hours - */ - public long toHours() - { - return unit.toHours(quantity); - } - - /** - * Returns this duration in number of minutes as an {@code int} - * - * @return this duration in number of minutes or {@code Integer.MAX_VALUE} if the number of minutes is too large. - */ - public int toHoursAsInt() - { - return Ints.saturatedCast(toHours()); - } - - /** - * @return this duration in number of minutes - */ - public long toMinutes() - { - return unit.toMinutes(quantity); - } - - /** - * Returns this duration in number of minutes as an {@code int} - * - * @return this duration in number of minutes or {@code Integer.MAX_VALUE} if the number of minutes is too large. - */ - public int toMinutesAsInt() - { - return Ints.saturatedCast(toMinutes()); - } - - /** - * @return this duration in number of seconds - */ - public long toSeconds() - { - return unit.toSeconds(quantity); - } - - /** - * Returns this duration in number of seconds as an {@code int} - * - * @return this duration in number of seconds or {@code Integer.MAX_VALUE} if the number of seconds is too large. - */ - public int toSecondsAsInt() - { - return Ints.saturatedCast(toSeconds()); - } - - /** - * @return this duration in number of nanoseconds - */ - public long toNanoseconds() - { - return unit.toNanos(quantity); - } - - /** - * Returns this duration in number of nanoseconds as an {@code int} - * - * @return this duration in number of nanoseconds or {@code Integer.MAX_VALUE} if the number of nanoseconds is too large. - */ - public int toNanosecondsAsInt() - { - return Ints.saturatedCast(toNanoseconds()); - } - - /** - * @return this duration in number of milliseconds - */ - public long toMilliseconds() - { - return unit.toMillis(quantity); - } - - /** - * @return the duration value in milliseconds - */ - public static long toMilliseconds(DurationSpec quantity) - { - return quantity.toMilliseconds(); - } - - /** - * Returns this duration in number of milliseconds as an {@code int} - * - * @return this duration in number of milliseconds or {@code Integer.MAX_VALUE} if the number of milliseconds is too large. - */ - public int toMillisecondsAsInt() - { - return Ints.saturatedCast(toMilliseconds()); - } - @Override public int hashCode() { @@ -368,7 +195,7 @@ public class DurationSpec @Override public String toString() { - return quantity + getSymbol(unit); + return quantity + symbol(unit); } /** @@ -377,7 +204,10 @@ public class DurationSpec * @param unit the time unit * @return the time unit symbol */ - static String getSymbol(TimeUnit unit) + // get vs no-get prefix is not consistent in the code base, but for classes involved with config parsing, it is + // imporant to be explicit about get/set as this changes how parsing is done; this class is a data-type, so is + // not nested, having get/set can confuse parsing thinking this is a nested type + static String symbol(TimeUnit unit) { switch (unit) { @@ -391,4 +221,387 @@ public class DurationSpec } throw new AssertionError(); } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in nanoseconds. + * If the user sets a different unit - we still validate that converted to nanoseconds the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongNanosecondsBound extends DurationSpec + { + /** + * Creates a {@code DurationSpec.LongNanosecondsBound} of the specified amount. + * The bound is [0, Long.MAX_VALUE) in nanoseconds. + * + * @param value the duration + */ + public LongNanosecondsBound(String value) + { + super(value, NANOSECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongNanosecondsBound} of the specified amount in the specified unit. + * The bound is [0, Long.MAX_VALUE) in nanoseconds. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in nanoseconds + * @param unit in which the provided quantity is + */ + public LongNanosecondsBound(long quantity, TimeUnit unit) + { + super(quantity, unit, NANOSECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongNanosecondsBound} of the specified amount in nanoseconds. + * The bound is [0, Long.MAX_VALUE) in nanoseconds. + * + * @param nanoseconds where nanoseconds shouldn't be bigger than Long.MAX_VALUE-1 + */ + public LongNanosecondsBound(long nanoseconds) + { + this(nanoseconds, NANOSECONDS); + } + + /** + * @return this duration in number of nanoseconds + */ + public long toNanoseconds() + { + return unit().toNanos(quantity()); + } + } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in milliseconds. + * If the user sets a different unit - we still validate that converted to milliseconds the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongMillisecondsBound extends DurationSpec + { + /** + * Creates a {@code DurationSpec.LongMillisecondsBound} of the specified amount. + * The bound is [0, Long.MAX_VALUE) in milliseconds. + * + * @param value the duration + */ + public LongMillisecondsBound(String value) + { + super(value, MILLISECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongMillisecondsBound} of the specified amount in the specified unit. + * The bound is [0, Long.MAX_VALUE) in milliseconds. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in milliseconds + * @param unit in which the provided quantity is + */ + public LongMillisecondsBound(long quantity, TimeUnit unit) + { + super(quantity, unit, MILLISECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongMillisecondsBound} of the specified amount in milliseconds. + * The bound is [0, Long.MAX_VALUE) in milliseconds. + * + * @param milliseconds where milliseconds shouldn't be bigger than Long.MAX_VALUE-1 + */ + public LongMillisecondsBound(long milliseconds) + { + this(milliseconds, MILLISECONDS); + } + + /** + * @return this duration in number of milliseconds + */ + public long toMilliseconds() + { + return unit().toMillis(quantity()); + } + } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Long.MAX_VALUE) in seconds. + * If the user sets a different unit - we still validate that converted to seconds the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class LongSecondsBound extends DurationSpec + { + /** + * Creates a {@code DurationSpec.LongSecondsBound} of the specified amount. + * The bound is [0, Long.MAX_VALUE) in seconds. + * + * @param value the duration + */ + public LongSecondsBound(String value) + { + super(value, SECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongSecondsBound} of the specified amount in the specified unit. + * The bound is [0, Long.MAX_VALUE) in seconds. + * + * @param quantity where quantity shouldn't be bigger than Long.MAX_VALUE - 1 in seconds + * @param unit in which the provided quantity is + */ + public LongSecondsBound(long quantity, TimeUnit unit) + { + super(quantity, unit, SECONDS, Long.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.LongSecondsBound} of the specified amount in seconds. + * The bound is [0, Long.MAX_VALUE) in seconds. + * + * @param seconds where seconds shouldn't be bigger than Long.MAX_VALUE-1 + */ + public LongSecondsBound(long seconds) + { + this(seconds, SECONDS); + } + + /** + * @return this duration in number of milliseconds + */ + public long toMilliseconds() + { + return unit().toMillis(quantity()); + } + + /** + * @return this duration in number of seconds + */ + public long toSeconds() + { + return unit().toSeconds(quantity()); + } + } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in minutes. + * If the user sets a different unit - we still validate that converted to minutes the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntMinutesBound extends DurationSpec + { + /** + * Creates a {@code DurationSpec.IntMinutesBound} of the specified amount. The bound is [0, Integer.MAX_VALUE) in minutes. + * The bound is [0, Integer.MAX_VALUE) in minutes. + * + * @param value the duration + */ + public IntMinutesBound(String value) + { + super(value, MINUTES, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntMinutesBound} of the specified amount in the specified unit. + * The bound is [0, Integer.MAX_VALUE) in minutes. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in minutes + * @param unit in which the provided quantity is + */ + public IntMinutesBound(long quantity, TimeUnit unit) + { + super(quantity, unit, MINUTES, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntMinutesBound} of the specified amount in minutes. + * The bound is [0, Integer.MAX_VALUE) in minutes. + * + * @param minutes where minutes shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntMinutesBound(long minutes) + { + this(minutes, MINUTES); + } + + /** + * Returns this duration in number of milliseconds as an {@code int} + * + * @return this duration in number of milliseconds or {@code Integer.MAX_VALUE} if the number of milliseconds is too large. + */ + public int toMilliseconds() + { + return Ints.saturatedCast(unit().toMillis(quantity())); + } + + /** + * Returns this duration in number of seconds as an {@code int} + * + * @return this duration in number of seconds or {@code Integer.MAX_VALUE} if the number of seconds is too large. + */ + public int toSeconds() + { + return Ints.saturatedCast(unit().toSeconds(quantity())); + } + + /** + * Returns this duration in number of minutes as an {@code int} + * + * @return this duration in number of minutes or {@code Integer.MAX_VALUE} if the number of minutes is too large. + */ + public int toMinutes() + { + return Ints.saturatedCast(unit().toMinutes(quantity())); + } + } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in seconds. + * If the user sets a different unit - we still validate that converted to seconds the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntSecondsBound extends DurationSpec + { + private static final Pattern VALUES_PATTERN = Pattern.compile(("\\d+")); + + /** + * Creates a {@code DurationSpec.IntSecondsBound} of the specified amount. The bound is [0, Integer.MAX_VALUE) in seconds. + * The bound is [0, Integer.MAX_VALUE) in seconds. + * + * @param value the duration + */ + public IntSecondsBound(String value) + { + super(value, SECONDS, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntSecondsBound} of the specified amount in the specified unit. + * The bound is [0, Integer.MAX_VALUE) in seconds. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in seconds + * @param unit in which the provided quantity is + */ + public IntSecondsBound(long quantity, TimeUnit unit) + { + super(quantity, unit, SECONDS, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntSecondsBound} of the specified amount in seconds. + * The bound is [0, Integer.MAX_VALUE) in seconds. + * + * @param seconds where seconds shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntSecondsBound(long seconds) + { + this(seconds, SECONDS); + } + + /** + * Creates a {@code DurationSpec.IntSecondsBound} of the specified amount in seconds, expressed either as the + * number of seconds without unit, or as a regular quantity with unit. + * Used in the Converters for a few parameters which changed only type, but not names + * The bound is [0, Integer.MAX_VALUE) in seconds. + * + * @param value where value shouldn't be bigger than Integer.MAX_VALUE-1 in seconds + */ + public static IntSecondsBound inSecondsString(String value) + { + //parse the string field value + Matcher matcher = VALUES_PATTERN.matcher(value); + + long seconds; + //if the provided string value is just a number, then we create a IntSecondsBound value in seconds + if (matcher.matches()) + { + seconds = Integer.parseInt(value); + return new IntSecondsBound(seconds, TimeUnit.SECONDS); + } + + //otherwise we just use the standard constructors + return new IntSecondsBound(value); + } + + /** + * Returns this duration in number of milliseconds as an {@code int} + * + * @return this duration in number of milliseconds or {@code Integer.MAX_VALUE} if the number of milliseconds is too large. + */ + public int toMilliseconds() + { + return Ints.saturatedCast(unit().toMillis(quantity())); + } + + /** + * Returns this duration in number of seconds as an {@code int} + * + * @return this duration in number of seconds or {@code Integer.MAX_VALUE} if the number of seconds is too large. + */ + public int toSeconds() + { + return Ints.saturatedCast(unit().toSeconds(quantity())); + } + } + + /** + * Represents a duration used for Cassandra configuration. The bound is [0, Integer.MAX_VALUE) in milliseconds. + * If the user sets a different unit - we still validate that converted to milliseconds the quantity will not exceed + * that upper bound. (CASSANDRA-17571) + */ + public final static class IntMillisecondsBound extends DurationSpec + { + /** + * Creates a {@code DurationSpec.IntMillisecondsBound} of the specified amount. The bound is [0, Integer.MAX_VALUE) in milliseconds. + * The bound is [0, Integer.MAX_VALUE) in milliseconds. + * + * @param value the duration + */ + public IntMillisecondsBound(String value) + { + super(value, MILLISECONDS, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntMillisecondsBound} of the specified amount in the specified unit. + * The bound is [0, Integer.MAX_VALUE) in milliseconds. + * + * @param quantity where quantity shouldn't be bigger than Integer.MAX_VALUE - 1 in milliseconds + * @param unit in which the provided quantity is + */ + public IntMillisecondsBound(long quantity, TimeUnit unit) + { + super(quantity, unit, MILLISECONDS, Integer.MAX_VALUE); + } + + /** + * Creates a {@code DurationSpec.IntMillisecondsBound} of the specified amount in milliseconds. + * The bound is [0, Integer.MAX_VALUE) in milliseconds. + * + * @param milliseconds where milliseconds shouldn't be bigger than Integer.MAX_VALUE-1 + */ + public IntMillisecondsBound(long milliseconds) + { + this(milliseconds, MILLISECONDS); + } + + /** + * Below constructor is used only for backward compatibility for the old commitlog_sync_group_window_in_ms before 4.1 + * Creates a {@code DurationSpec.IntMillisecondsBound} of the specified amount in the specified unit. + * + * @param quantity where quantity shouldn't be bigger than Intetger.MAX_VALUE - 1 in milliseconds + * @param unit in which the provided quantity is + */ + public IntMillisecondsBound(double quantity, TimeUnit unit) + { + super(quantity, unit, MILLISECONDS, Integer.MAX_VALUE); + } + + /** + * Returns this duration in number of milliseconds as an {@code int} + * + * @return this duration in number of milliseconds or {@code Integer.MAX_VALUE} if the number of milliseconds is too large. + */ + public int toMilliseconds() + { + return Ints.saturatedCast(unit().toMillis(quantity())); + } + } } diff --git a/src/java/org/apache/cassandra/config/GuardrailsOptions.java b/src/java/org/apache/cassandra/config/GuardrailsOptions.java index 301a2527ee..b14f428ca4 100644 --- a/src/java/org/apache/cassandra/config/GuardrailsOptions.java +++ b/src/java/org/apache/cassandra/config/GuardrailsOptions.java @@ -509,19 +509,19 @@ public class GuardrailsOptions implements GuardrailsConfig @Override @Nullable - public DataStorageSpec getCollectionSizeWarnThreshold() + public DataStorageSpec.LongBytesBound getCollectionSizeWarnThreshold() { return config.collection_size_warn_threshold; } @Override @Nullable - public DataStorageSpec getCollectionSizeFailThreshold() + public DataStorageSpec.LongBytesBound getCollectionSizeFailThreshold() { return config.collection_size_fail_threshold; } - public void setCollectionSizeThreshold(@Nullable DataStorageSpec warn, @Nullable DataStorageSpec fail) + public void setCollectionSizeThreshold(@Nullable DataStorageSpec.LongBytesBound warn, @Nullable DataStorageSpec.LongBytesBound fail) { validateSizeThreshold(warn, fail, false, "collection_size"); updatePropertyWithLogging("collection_size_warn_threshold", @@ -609,12 +609,12 @@ public class GuardrailsOptions implements GuardrailsConfig } @Override - public DataStorageSpec getDataDiskUsageMaxDiskSize() + public DataStorageSpec.LongBytesBound getDataDiskUsageMaxDiskSize() { return config.data_disk_usage_max_disk_size; } - public void setDataDiskUsageMaxDiskSize(@Nullable DataStorageSpec diskSize) + public void setDataDiskUsageMaxDiskSize(@Nullable DataStorageSpec.LongBytesBound diskSize) { validateDataDiskUsageMaxDiskSize(diskSize); updatePropertyWithLogging("data_disk_usage_max_disk_size", @@ -738,7 +738,7 @@ public class GuardrailsOptions implements GuardrailsConfig } } - private static void validateSize(DataStorageSpec size, boolean allowZero, String name) + private static void validateSize(DataStorageSpec.LongBytesBound size, boolean allowZero, String name) { if (size == null) return; @@ -749,14 +749,14 @@ public class GuardrailsOptions implements GuardrailsConfig name)); } - private static void validateSizeThreshold(DataStorageSpec warn, DataStorageSpec fail, boolean allowZero, String name) + private static void validateSizeThreshold(DataStorageSpec.LongBytesBound warn, DataStorageSpec.LongBytesBound fail, boolean allowZero, String name) { validateSize(warn, allowZero, name + "_warn_threshold"); validateSize(fail, allowZero, name + "_fail_threshold"); validateWarnLowerThanFail(warn, fail, name); } - private static void validateWarnLowerThanFail(DataStorageSpec warn, DataStorageSpec fail, String name) + private static void validateWarnLowerThanFail(DataStorageSpec.LongBytesBound warn, DataStorageSpec.LongBytesBound fail, String name) { if (warn == null || fail == null) return; @@ -790,7 +790,7 @@ public class GuardrailsOptions implements GuardrailsConfig return consistencyLevels.isEmpty() ? Collections.emptySet() : Sets.immutableEnumSet(consistencyLevels); } - private static void validateDataDiskUsageMaxDiskSize(DataStorageSpec maxDiskSize) + private static void validateDataDiskUsageMaxDiskSize(DataStorageSpec.LongBytesBound maxDiskSize) { if (maxDiskSize == null) return; diff --git a/src/java/org/apache/cassandra/config/SmallestDataStorageKibibytes.java b/src/java/org/apache/cassandra/config/SmallestDataStorageKibibytes.java deleted file mode 100644 index 375af293a8..0000000000 --- a/src/java/org/apache/cassandra/config/SmallestDataStorageKibibytes.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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; - -/** - * Wrapper class for Cassandra data storage configuration parameters which are internally represented in Kibibytes. In order - * not to lose precision while converting to smaller units (until we migrate those parameters to use internally the smallest - * supported unit) we restrict those parameters to use only kibibytes or larger units. (CASSANDRA-15234) - */ -public final class SmallestDataStorageKibibytes extends DataStorageSpec -{ - /** - * Creates a {@code SmallestDataStorageKibibytes} of the specified amount of seconds and provides the smallest - * required unit of Kibibytes for the respective parameter of type {@code SmallestDurationSeconds}. - * - * @param value the data storage - * - */ - public SmallestDataStorageKibibytes(String value) - { - super(value, DataStorageSpec.DataStorageUnit.KIBIBYTES); - } - - private SmallestDataStorageKibibytes(long quantity, DataStorageSpec.DataStorageUnit unit) - { - super(quantity, unit); - } - - /** - * Creates a {@code SmallestDataStorageKibibytes} of the specified amount of kibibytes. - * - * @param kibibytes the amount of kibibytes - * @return a data storage - */ - public static SmallestDataStorageKibibytes inKibibytes(long kibibytes) - { - return new SmallestDataStorageKibibytes(kibibytes, DataStorageSpec.DataStorageUnit.KIBIBYTES); - } -} diff --git a/src/java/org/apache/cassandra/config/SmallestDataStorageMebibytes.java b/src/java/org/apache/cassandra/config/SmallestDataStorageMebibytes.java deleted file mode 100644 index 514d1bc18a..0000000000 --- a/src/java/org/apache/cassandra/config/SmallestDataStorageMebibytes.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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; - -/** - * Wrapper class for Cassandra data storage configuration parameters which are internally represented in mebibytes. In order - * not to lose precision while converting to smaller units (until we migrate those parameters to use internally the smallest - * supported unit) we restrict those parameters to use only mebibytes or larger units. (CASSANDRA-15234) - */ -public final class SmallestDataStorageMebibytes extends DataStorageSpec -{ - /** - * Creates a {@code SmallestDataStoragemebibytes} of the specified amount of seconds and provides the smallest - * required unit of mebibytes for the respective parameter of type {@code SmallestDurationSeconds}. - * - * @param value the data storage - * - */ - public SmallestDataStorageMebibytes(String value) - { - super(value, DataStorageSpec.DataStorageUnit.MEBIBYTES); - } - - private SmallestDataStorageMebibytes(long quantity, DataStorageSpec.DataStorageUnit unit) - { - super(quantity, unit); - } - - /** - * Creates a {@code SmallestDataStorageMebibytes} of the specified amount of mebibytes. - * - * @param mebibytes the amount of mebibytes - * @return a data storage - */ - public static SmallestDataStorageMebibytes inMebibytes(long mebibytes) - { - return new SmallestDataStorageMebibytes(mebibytes, DataStorageSpec.DataStorageUnit.MEBIBYTES); - } - - /** - * Creates a {@code SmallestDataStorageMebibytes} of the specified amount of bytes. - * - * @param bytes the amount of bytes - * @return a data storage - */ - public static SmallestDataStorageMebibytes inBytes(long bytes) - { - return new SmallestDataStorageMebibytes(bytes, DataStorageSpec.DataStorageUnit.BYTES); - } -} diff --git a/src/java/org/apache/cassandra/config/SmallestDurationMilliseconds.java b/src/java/org/apache/cassandra/config/SmallestDurationMilliseconds.java deleted file mode 100644 index 5a152f56d0..0000000000 --- a/src/java/org/apache/cassandra/config/SmallestDurationMilliseconds.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 static java.util.concurrent.TimeUnit.MILLISECONDS; - -/** - * Wrapper class for Cassandra duration configuration parameters which are internally represented in Milliseconds. In order - * not to lose precision while converting to smaller units (until we migrate those parameters to use internally the smallest - * supported unit) we restrict those parameters to use only Milliseconds or larger units. (CASSANDRA-15234) - */ -public final class SmallestDurationMilliseconds extends DurationSpec -{ - /** - * Creates a {@code SmallestDurationMilliseconds} of the specified amount of milliseconds and provides the smallest - * required unit of milliseconds for the respective parameter of type {@code SmallestDurationMilliseconds}. - * - * @param value the duration - * - */ - public SmallestDurationMilliseconds(String value) - { - super(value, TimeUnit.MILLISECONDS); - } - - private SmallestDurationMilliseconds(long quantity, TimeUnit unit) - { - super(quantity, unit); - } - - private SmallestDurationMilliseconds(double quantity, TimeUnit unit) - { - super(quantity, unit); - } - - /** - * Creates a {@code SmallestDurationMilliseconds} of the specified amount of milliseconds. - * - * @param milliseconds the amount of milliseconds - * @return a duration - */ - public static SmallestDurationMilliseconds inMilliseconds(long milliseconds) - { - return new SmallestDurationMilliseconds(milliseconds, TimeUnit.MILLISECONDS); - } - - public static SmallestDurationMilliseconds inDoubleMilliseconds(double milliseconds) - { - return new SmallestDurationMilliseconds(milliseconds, MILLISECONDS); - } -} diff --git a/src/java/org/apache/cassandra/config/SmallestDurationMinutes.java b/src/java/org/apache/cassandra/config/SmallestDurationMinutes.java deleted file mode 100644 index 50992398ea..0000000000 --- a/src/java/org/apache/cassandra/config/SmallestDurationMinutes.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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; - -/** - * Wrapper class for Cassandra duration configuration parameters which are internally represented in Minuts. In order - * not to lose precision while converting to smaller units (until we migrate those parameters to use internally the smallest - * supported unit) we restrict those parameters to use only Minutes or larger units. (CASSANDRA-15234) - */ -public final class SmallestDurationMinutes extends DurationSpec -{ - /** - * Creates a {@code SmallestDurationMinutes} of the specified amount of minutes and provides the smallest - * required unit of minutes for the respective parameter of type {@code SmallestDurationMinutes}. - * - * @param value the duration - * - */ - public SmallestDurationMinutes(String value) - { - super(value, TimeUnit.MINUTES); - } - - private SmallestDurationMinutes(long quantity, TimeUnit unit) - { - super(quantity, unit); - } - - /** - * Creates a {@code SmallestDurationMinutes} of the specified amount of minutes. - * - * @param minutes the amount of minutes - * @return a duration - */ - public static SmallestDurationMinutes inMinutes(long minutes) - { - return new SmallestDurationMinutes(minutes, TimeUnit.MINUTES); - } -} diff --git a/src/java/org/apache/cassandra/config/SmallestDurationSeconds.java b/src/java/org/apache/cassandra/config/SmallestDurationSeconds.java deleted file mode 100644 index f7323153ad..0000000000 --- a/src/java/org/apache/cassandra/config/SmallestDurationSeconds.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Wrapper class for Cassandra duration configuration parameters which are internally represented in Seconds. In order - * not to lose precision while converting to smaller units (until we migrate those parameters to use internally the smallest - * supported unit) we restrict those parameters to use only Seconds or larger units. (CASSANDRA-15234) - */ -public final class SmallestDurationSeconds extends DurationSpec -{ - private static final Pattern VALUES_PATTERN = Pattern.compile(("\\d+")); - - /** - * Creates a {@code SmallestDurationSeconds} of the specified amount of seconds and provides the smallest - * required unit of seconds for the respective parameter of type {@code SmallestDurationSeconds}. - * - * @param value the duration - * - */ - public SmallestDurationSeconds(String value) - { - super(value, TimeUnit.SECONDS); - } - - private SmallestDurationSeconds(long quantity, TimeUnit unit) - { - super(quantity, unit); - } - - /** - * Creates a {@code SmallestDurationSeconds} of the specified amount of seconds. - * - * @param seconds the amount of seconds - * @return a duration - */ - public static SmallestDurationSeconds inSeconds(long seconds) - { - return new SmallestDurationSeconds(seconds, TimeUnit.SECONDS); - } - - /** - * Creates a {@code SmallestDurationSeconds} of the specified amount of seconds. Custom method for special cases. - * - * @param value which can be in the old form only presenting the quantity or the post CASSANDRA-15234 form - a - * value consisting of quantity and unit. This method is necessary for three parameters which didn't change their - * names but only their value format. (key_cache_save_period, row_cache_save_period, counter_cache_save_period) - * @return a duration - */ - public static SmallestDurationSeconds inSecondsString(String value) - { - //parse the string field value - Matcher matcher = VALUES_PATTERN.matcher(value); - - long seconds; - //if the provided string value is just a number, then we create a Duration Spec value in seconds - if (matcher.matches()) - { - seconds = Long.parseLong(value); - return new SmallestDurationSeconds(seconds, TimeUnit.SECONDS); - } - - //otherwise we just use the standard constructors - return new SmallestDurationSeconds(value); - } -} diff --git a/src/java/org/apache/cassandra/cql3/QueryOptions.java b/src/java/org/apache/cassandra/cql3/QueryOptions.java index 5fcaf06786..a286aed5df 100644 --- a/src/java/org/apache/cassandra/cql3/QueryOptions.java +++ b/src/java/org/apache/cassandra/cql3/QueryOptions.java @@ -296,7 +296,7 @@ public abstract class QueryOptions private final long warnThresholdBytes; private final long abortThresholdBytes; - public DefaultReadThresholds(DataStorageSpec warnThreshold, DataStorageSpec abortThreshold) + public DefaultReadThresholds(DataStorageSpec.LongBytesBound warnThreshold, DataStorageSpec.LongBytesBound abortThreshold) { this.warnThresholdBytes = warnThreshold == null ? -1 : warnThreshold.toBytes(); this.abortThresholdBytes = abortThreshold == null ? -1 : abortThreshold.toBytes(); diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java index 0057300690..bf43f327e3 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java @@ -2002,7 +2002,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner /** * @param ephemeral If this flag is set to true, the snapshot will be cleaned during next startup */ - public TableSnapshot snapshotWithoutMemtable(String snapshotName, Predicate predicate, boolean ephemeral, DurationSpec ttl, RateLimiter rateLimiter, Instant creationTime) + public TableSnapshot snapshotWithoutMemtable(String snapshotName, Predicate predicate, boolean ephemeral, DurationSpec.IntSecondsBound ttl, RateLimiter rateLimiter, Instant creationTime) { if (ephemeral && ttl != null) { @@ -2032,7 +2032,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner return createSnapshot(snapshotName, ephemeral, ttl, snapshottedSSTables, creationTime); } - protected TableSnapshot createSnapshot(String tag, boolean ephemeral, DurationSpec ttl, Set sstables, Instant creationTime) { + protected TableSnapshot createSnapshot(String tag, boolean ephemeral, DurationSpec.IntSecondsBound ttl, Set sstables, Instant creationTime) { Set snapshotDirs = sstables.stream() .map(s -> Directories.getSnapshotDirectory(s.descriptor, tag).toAbsolute()) .filter(dir -> !Directories.isSecondaryIndexFolder(dir)) // Remove secondary index subdirectory @@ -2187,7 +2187,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner return snapshot(snapshotName, null); } - public TableSnapshot snapshot(String snapshotName, DurationSpec ttl) + public TableSnapshot snapshot(String snapshotName, DurationSpec.IntSecondsBound ttl) { return snapshot(snapshotName, false, ttl, null, now()); } @@ -2201,7 +2201,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner * @param rateLimiter Rate limiter for hardlinks-per-second * @param creationTime time when this snapshot was taken */ - public TableSnapshot snapshot(String snapshotName, boolean skipMemtable, DurationSpec ttl, RateLimiter rateLimiter, Instant creationTime) + public TableSnapshot snapshot(String snapshotName, boolean skipMemtable, DurationSpec.IntSecondsBound ttl, RateLimiter rateLimiter, Instant creationTime) { return snapshot(snapshotName, null, false, skipMemtable, ttl, rateLimiter, creationTime); } @@ -2223,7 +2223,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean, Memtable.Owner * @param rateLimiter Rate limiter for hardlinks-per-second * @param creationTime time when this snapshot was taken */ - public TableSnapshot snapshot(String snapshotName, Predicate predicate, boolean ephemeral, boolean skipMemtable, DurationSpec ttl, RateLimiter rateLimiter, Instant creationTime) + public TableSnapshot snapshot(String snapshotName, Predicate predicate, boolean ephemeral, boolean skipMemtable, DurationSpec.IntSecondsBound ttl, RateLimiter rateLimiter, Instant creationTime) { if (!skipMemtable) { diff --git a/src/java/org/apache/cassandra/db/Keyspace.java b/src/java/org/apache/cassandra/db/Keyspace.java index 95eb966c93..63c02be5db 100644 --- a/src/java/org/apache/cassandra/db/Keyspace.java +++ b/src/java/org/apache/cassandra/db/Keyspace.java @@ -230,7 +230,7 @@ public class Keyspace * @param rateLimiter Rate limiter for hardlinks-per-second * @throws IOException if the column family doesn't exist */ - public void snapshot(String snapshotName, String columnFamilyName, boolean skipFlush, DurationSpec ttl, RateLimiter rateLimiter, Instant creationTime) throws IOException + public void snapshot(String snapshotName, String columnFamilyName, boolean skipFlush, DurationSpec.IntSecondsBound ttl, RateLimiter rateLimiter, Instant creationTime) throws IOException { assert snapshotName != null; boolean tookSnapShot = false; diff --git a/src/java/org/apache/cassandra/db/ReadCommand.java b/src/java/org/apache/cassandra/db/ReadCommand.java index ef70588a45..358d408919 100644 --- a/src/java/org/apache/cassandra/db/ReadCommand.java +++ b/src/java/org/apache/cassandra/db/ReadCommand.java @@ -653,7 +653,7 @@ public abstract class ReadCommand extends AbstractReadQuery } } - private boolean shouldTrackSize(DataStorageSpec warnThresholdBytes, DataStorageSpec abortThresholdBytes) + private boolean shouldTrackSize(DataStorageSpec.LongBytesBound warnThresholdBytes, DataStorageSpec.LongBytesBound abortThresholdBytes) { return trackWarnings && !SchemaConstants.isSystemKeyspace(metadata().keyspace) @@ -662,8 +662,8 @@ public abstract class ReadCommand extends AbstractReadQuery private UnfilteredPartitionIterator withQuerySizeTracking(UnfilteredPartitionIterator iterator) { - DataStorageSpec warnThreshold = DatabaseDescriptor.getLocalReadSizeWarnThreshold(); - DataStorageSpec failThreshold = DatabaseDescriptor.getLocalReadSizeFailThreshold(); + DataStorageSpec.LongBytesBound warnThreshold = DatabaseDescriptor.getLocalReadSizeWarnThreshold(); + DataStorageSpec.LongBytesBound failThreshold = DatabaseDescriptor.getLocalReadSizeFailThreshold(); if (!shouldTrackSize(warnThreshold, failThreshold)) return iterator; final long warnBytes = warnThreshold == null ? -1 : warnThreshold.toBytes(); diff --git a/src/java/org/apache/cassandra/db/RowIndexEntry.java b/src/java/org/apache/cassandra/db/RowIndexEntry.java index addeaf82ef..80f53a9e72 100644 --- a/src/java/org/apache/cassandra/db/RowIndexEntry.java +++ b/src/java/org/apache/cassandra/db/RowIndexEntry.java @@ -356,8 +356,8 @@ public class RowIndexEntry implements IMeasurableMemory if (command == null || SchemaConstants.isSystemKeyspace(command.metadata().keyspace) || !DatabaseDescriptor.getReadThresholdsEnabled()) return; - DataStorageSpec warnThreshold = DatabaseDescriptor.getRowIndexReadSizeWarnThreshold(); - DataStorageSpec failThreshold = DatabaseDescriptor.getRowIndexReadSizeFailThreshold(); + DataStorageSpec.LongBytesBound warnThreshold = DatabaseDescriptor.getRowIndexReadSizeWarnThreshold(); + DataStorageSpec.LongBytesBound failThreshold = DatabaseDescriptor.getRowIndexReadSizeFailThreshold(); if (warnThreshold == null && failThreshold == null) return; diff --git a/src/java/org/apache/cassandra/db/guardrails/Guardrails.java b/src/java/org/apache/cassandra/db/guardrails/Guardrails.java index a991f69f6e..57dd2af5ce 100644 --- a/src/java/org/apache/cassandra/db/guardrails/Guardrails.java +++ b/src/java/org/apache/cassandra/db/guardrails/Guardrails.java @@ -920,7 +920,7 @@ public final class Guardrails implements GuardrailsMBean return set.stream().map(ConsistencyLevel::valueOf).collect(Collectors.toSet()); } - private static Long sizeToBytes(@Nullable DataStorageSpec size) + private static Long sizeToBytes(@Nullable DataStorageSpec.LongBytesBound size) { return size == null ? -1 : size.toBytes(); } @@ -930,8 +930,8 @@ public final class Guardrails implements GuardrailsMBean return size == null ? null : size.toString(); } - private static DataStorageSpec sizeFromString(@Nullable String size) + private static DataStorageSpec.LongBytesBound sizeFromString(@Nullable String size) { - return StringUtils.isEmpty(size) ? null : new DataStorageSpec(size); + return StringUtils.isEmpty(size) ? null : new DataStorageSpec.LongBytesBound(size); } } diff --git a/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java b/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java index 4fcfb18823..7f38e80ec3 100644 --- a/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java +++ b/src/java/org/apache/cassandra/db/guardrails/GuardrailsConfig.java @@ -227,13 +227,13 @@ public interface GuardrailsConfig * @return The threshold to warn when encountering a collection with larger data size than threshold. */ @Nullable - DataStorageSpec getCollectionSizeWarnThreshold(); + DataStorageSpec.LongBytesBound getCollectionSizeWarnThreshold(); /** * @return The threshold to prevent collections with larger data size than threshold. */ @Nullable - DataStorageSpec getCollectionSizeFailThreshold(); + DataStorageSpec.LongBytesBound getCollectionSizeFailThreshold(); /** * @return The threshold to warn when encountering more elements in a collection than threshold. @@ -272,7 +272,7 @@ public interface GuardrailsConfig * disabled. */ @Nullable - DataStorageSpec getDataDiskUsageMaxDiskSize(); + DataStorageSpec.LongBytesBound getDataDiskUsageMaxDiskSize(); /** * @return The threshold to warn when replication factor is lesser than threshold. diff --git a/src/java/org/apache/cassandra/db/virtual/SettingsTable.java b/src/java/org/apache/cassandra/db/virtual/SettingsTable.java index 82cf2897fc..7a4c39e647 100644 --- a/src/java/org/apache/cassandra/db/virtual/SettingsTable.java +++ b/src/java/org/apache/cassandra/db/virtual/SettingsTable.java @@ -20,7 +20,6 @@ package org.apache.cassandra.db.virtual; import java.util.HashMap; import java.util.Map; import java.util.Objects; - import com.google.common.collect.ImmutableMap; import org.apache.cassandra.config.Config; diff --git a/src/java/org/apache/cassandra/service/ActiveRepairService.java b/src/java/org/apache/cassandra/service/ActiveRepairService.java index 85f5447a19..745067d6cd 100644 --- a/src/java/org/apache/cassandra/service/ActiveRepairService.java +++ b/src/java/org/apache/cassandra/service/ActiveRepairService.java @@ -234,7 +234,7 @@ public class ActiveRepairService implements IEndpointStateChangeSubscriber, IFai .maximumSize(Long.getLong("cassandra.parent_repair_status_cache_size", 100_000)) .build(); - DurationSpec duration = getRepairStateExpires(); + DurationSpec.LongNanosecondsBound duration = getRepairStateExpires(); int numElements = getRepairStateSize(); logger.info("Storing repair state for {} or for {} elements", duration, numElements); repairs = CacheBuilder.newBuilder() diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 77f53f7770..34fb6acb17 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -3885,7 +3885,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE @Override public void takeSnapshot(String tag, Map options, String... entities) throws IOException { - DurationSpec ttl = options.containsKey("ttl") ? new DurationSpec(options.get("ttl")) : null; + DurationSpec.IntSecondsBound ttl = options.containsKey("ttl") ? new DurationSpec.IntSecondsBound(options.get("ttl")) : null; if (ttl != null) { int minAllowedTtlSecs = CassandraRelevantProperties.SNAPSHOT_MIN_ALLOWED_TTL_SECONDS.getInt(); @@ -3988,7 +3988,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE * @param skipFlush Skip blocking flush of memtable * @param keyspaceNames the names of the keyspaces to snapshot; empty means "all." */ - private void takeSnapshot(String tag, boolean skipFlush, DurationSpec ttl, String... keyspaceNames) throws IOException + private void takeSnapshot(String tag, boolean skipFlush, DurationSpec.IntSecondsBound ttl, String... keyspaceNames) throws IOException { if (operationMode == Mode.JOINING) throw new IOException("Cannot snapshot until bootstrap completes"); @@ -4034,7 +4034,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE * @param tableList * list of tables from different keyspace in the form of ks1.cf1 ks2.cf2 */ - private void takeMultipleTableSnapshot(String tag, boolean skipFlush, DurationSpec ttl, String... tableList) + private void takeMultipleTableSnapshot(String tag, boolean skipFlush, DurationSpec.IntSecondsBound ttl, String... tableList) throws IOException { Map> keyspaceColumnfamily = new HashMap>(); @@ -6520,11 +6520,11 @@ public class StorageService extends NotificationBroadcasterSupport implements IE logger.info("set default keyspace rf to {}", value); } - private static DataStorageSpec parseDataStorageSpec(String threshold) + private static DataStorageSpec.LongBytesBound parseDataStorageSpec(String threshold) { return threshold == null ? null - : new DataStorageSpec(threshold); + : new DataStorageSpec.LongBytesBound(threshold); } public int getDefaultKeyspaceReplicationFactor() @@ -6597,7 +6597,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE public void setPaxosPurgeGraceSeconds(long v) { - DatabaseDescriptor.setPaxosPurgeGrace(v, SECONDS); + DatabaseDescriptor.setPaxosPurgeGrace(v); logger.info("paxos purging grace seconds set to {} via jmx", v); } diff --git a/src/java/org/apache/cassandra/service/disk/usage/DiskUsageMonitor.java b/src/java/org/apache/cassandra/service/disk/usage/DiskUsageMonitor.java index 730e53e0f1..fc0bb3a554 100644 --- a/src/java/org/apache/cassandra/service/disk/usage/DiskUsageMonitor.java +++ b/src/java/org/apache/cassandra/service/disk/usage/DiskUsageMonitor.java @@ -140,7 +140,7 @@ public class DiskUsageMonitor BigInteger total = used.add(usable); // That total space can be limited by the config property data_disk_usage_max_disk_size. - DataStorageSpec diskUsageMaxSize = guardrailsConfigSupplier.get().getDataDiskUsageMaxDiskSize(); + DataStorageSpec.LongBytesBound diskUsageMaxSize = guardrailsConfigSupplier.get().getDataDiskUsageMaxDiskSize(); if (diskUsageMaxSize != null) total = total.min(BigInteger.valueOf(diskUsageMaxSize.toBytes())); diff --git a/src/java/org/apache/cassandra/service/snapshot/SnapshotManifest.java b/src/java/org/apache/cassandra/service/snapshot/SnapshotManifest.java index c5e696e73b..ba840efb77 100644 --- a/src/java/org/apache/cassandra/service/snapshot/SnapshotManifest.java +++ b/src/java/org/apache/cassandra/service/snapshot/SnapshotManifest.java @@ -54,11 +54,11 @@ public class SnapshotManifest this.expiresAt = null; } - public SnapshotManifest(List files, DurationSpec ttl, Instant creationTime) + public SnapshotManifest(List files, DurationSpec.IntSecondsBound ttl, Instant creationTime) { this.files = files; this.createdAt = creationTime; - this.expiresAt = ttl == null ? null : createdAt.plusMillis(ttl.toMilliseconds()); + this.expiresAt = ttl == null ? null : createdAt.plusSeconds(ttl.toSeconds()); } public List getFiles() diff --git a/src/java/org/apache/cassandra/streaming/StreamManager.java b/src/java/org/apache/cassandra/streaming/StreamManager.java index e258365376..40ac7d5252 100644 --- a/src/java/org/apache/cassandra/streaming/StreamManager.java +++ b/src/java/org/apache/cassandra/streaming/StreamManager.java @@ -253,7 +253,7 @@ public class StreamManager implements StreamManagerMBean public StreamManager() { - DurationSpec duration = DatabaseDescriptor.getStreamingStateExpires(); + DurationSpec.LongNanosecondsBound duration = DatabaseDescriptor.getStreamingStateExpires(); long sizeBytes = DatabaseDescriptor.getStreamingStateSize().toBytes(); long numElements = sizeBytes / StreamingState.ELEMENT_SIZE; logger.info("Storing streaming state for {} or for {} elements", duration, numElements); diff --git a/src/java/org/apache/cassandra/tools/LoaderOptions.java b/src/java/org/apache/cassandra/tools/LoaderOptions.java index e73f38f288..b9d06df599 100644 --- a/src/java/org/apache/cassandra/tools/LoaderOptions.java +++ b/src/java/org/apache/cassandra/tools/LoaderOptions.java @@ -397,15 +397,26 @@ public class LoaderOptions errorMsg("Config file not found", options); } config = new YamlConfigurationLoader().loadConfig(configFile.toPath().toUri().toURL()); + + // below 2 checks are needed in order to match the pre-CASSANDRA-15234 upper bound for those parameters which were still in megabits per second + if (config.stream_throughput_outbound.toMegabitsPerSecond() >= Integer.MAX_VALUE) + { + throw new ConfigurationException("Invalid value of stream_throughput_outbound: " + config.stream_throughput_outbound.toString(), false); + } + + if (config.inter_dc_stream_throughput_outbound.toMegabitsPerSecond() >= Integer.MAX_VALUE) + { + throw new ConfigurationException("Invalid value of inter_dc_stream_throughput_outbound: " + config.inter_dc_stream_throughput_outbound.toString(), false); + } } else { config = new Config(); // unthrottle stream by default - config.stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(0); - config.inter_dc_stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(0); - config.entire_sstable_stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(0); - config.entire_sstable_inter_dc_stream_throughput_outbound = DataRateSpec.inMebibytesPerSecond(0); + config.stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(0); + config.inter_dc_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(0); + config.entire_sstable_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(0); + config.entire_sstable_inter_dc_stream_throughput_outbound = new DataRateSpec.IntMebibytesPerSecondBound(0); } if (cmd.hasOption(STORAGE_PORT_OPTION)) diff --git a/src/java/org/apache/cassandra/tools/nodetool/Snapshot.java b/src/java/org/apache/cassandra/tools/nodetool/Snapshot.java index a4b432f686..52cc5df27c 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/Snapshot.java +++ b/src/java/org/apache/cassandra/tools/nodetool/Snapshot.java @@ -70,7 +70,7 @@ public class Snapshot extends NodeToolCmd Map options = new HashMap(); options.put("skipFlush", Boolean.toString(skipFlush)); if (null != ttl) { - DurationSpec d = new DurationSpec(ttl); + DurationSpec.LongNanosecondsBound d = new DurationSpec.LongNanosecondsBound(ttl); options.put("ttl", d.toString()); } diff --git a/test/conf/cassandra-sslcontextfactory-invalidconfiguration.yaml b/test/conf/cassandra-sslcontextfactory-invalidconfiguration.yaml index 1e473ae869..d3970cbf98 100644 --- a/test/conf/cassandra-sslcontextfactory-invalidconfiguration.yaml +++ b/test/conf/cassandra-sslcontextfactory-invalidconfiguration.yaml @@ -76,7 +76,7 @@ scripted_user_defined_functions_enabled: true prepared_statements_cache_size: 1MiB corrupted_tombstone_strategy: exception stream_entire_sstables: true -stream_throughput_outbound: 23841823841858MiB/s +stream_throughput_outbound: 23841858MiB/s sasi_indexes_enabled: true materialized_views_enabled: true file_cache_enabled: true diff --git a/test/distributed/org/apache/cassandra/distributed/test/thresholds/CoordinatorReadSizeWarningTest.java b/test/distributed/org/apache/cassandra/distributed/test/thresholds/CoordinatorReadSizeWarningTest.java index a1fad44ae7..31469aff18 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/thresholds/CoordinatorReadSizeWarningTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/thresholds/CoordinatorReadSizeWarningTest.java @@ -26,6 +26,7 @@ import org.junit.*; import org.apache.cassandra.config.DataStorageSpec; import org.apache.cassandra.config.DatabaseDescriptor; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.assertj.core.api.Assertions.assertThat; /** @@ -42,8 +43,8 @@ public class CoordinatorReadSizeWarningTest extends AbstractClientSizeWarning // setup threshold after init to avoid driver issues loading // the test uses a rather small limit, which causes driver to fail while loading metadata CLUSTER.stream().forEach(i -> i.runOnInstance(() -> { - DatabaseDescriptor.setCoordinatorReadSizeWarnThreshold(DataStorageSpec.inKibibytes(1)); - DatabaseDescriptor.setCoordinatorReadSizeFailThreshold(DataStorageSpec.inKibibytes(2)); + DatabaseDescriptor.setCoordinatorReadSizeWarnThreshold(new DataStorageSpec.LongBytesBound(1, KIBIBYTES)); + DatabaseDescriptor.setCoordinatorReadSizeFailThreshold(new DataStorageSpec.LongBytesBound(2, KIBIBYTES)); })); } diff --git a/test/distributed/org/apache/cassandra/distributed/test/thresholds/LocalReadSizeWarningTest.java b/test/distributed/org/apache/cassandra/distributed/test/thresholds/LocalReadSizeWarningTest.java index 2c5e45b2f3..31a9415f2c 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/thresholds/LocalReadSizeWarningTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/thresholds/LocalReadSizeWarningTest.java @@ -26,6 +26,7 @@ import org.junit.BeforeClass; import org.apache.cassandra.config.DataStorageSpec; import org.apache.cassandra.config.DatabaseDescriptor; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.assertj.core.api.Assertions.assertThat; public class LocalReadSizeWarningTest extends AbstractClientSizeWarning @@ -42,8 +43,8 @@ public class LocalReadSizeWarningTest extends AbstractClientSizeWarning DatabaseDescriptor.setCoordinatorReadSizeWarnThreshold(null); DatabaseDescriptor.setCoordinatorReadSizeFailThreshold(null); - DatabaseDescriptor.setLocalReadSizeWarnThreshold(DataStorageSpec.inKibibytes(1)); - DatabaseDescriptor.setLocalReadSizeFailThreshold(DataStorageSpec.inKibibytes(2)); + DatabaseDescriptor.setLocalReadSizeWarnThreshold(new DataStorageSpec.LongBytesBound(1, KIBIBYTES)); + DatabaseDescriptor.setLocalReadSizeFailThreshold(new DataStorageSpec.LongBytesBound(2, KIBIBYTES)); })); } diff --git a/test/distributed/org/apache/cassandra/distributed/test/thresholds/RowIndexSizeWarningTest.java b/test/distributed/org/apache/cassandra/distributed/test/thresholds/RowIndexSizeWarningTest.java index 513f00de4b..33e6cd6f38 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/thresholds/RowIndexSizeWarningTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/thresholds/RowIndexSizeWarningTest.java @@ -27,6 +27,7 @@ import org.junit.BeforeClass; import org.apache.cassandra.config.DataStorageSpec; import org.apache.cassandra.config.DatabaseDescriptor; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.assertj.core.api.Assertions.assertThat; public class RowIndexSizeWarningTest extends AbstractClientSizeWarning @@ -37,8 +38,8 @@ public class RowIndexSizeWarningTest extends AbstractClientSizeWarning AbstractClientSizeWarning.setupClass(); CLUSTER.stream().forEach(i -> i.runOnInstance(() -> { - DatabaseDescriptor.setRowIndexReadSizeWarnThreshold(DataStorageSpec.inKibibytes(1)); - DatabaseDescriptor.setRowIndexReadSizeFailThreshold(DataStorageSpec.inKibibytes(2)); + DatabaseDescriptor.setRowIndexReadSizeWarnThreshold(new DataStorageSpec.LongBytesBound(1, KIBIBYTES)); + DatabaseDescriptor.setRowIndexReadSizeFailThreshold(new DataStorageSpec.LongBytesBound(2, KIBIBYTES)); // hack to force multiple index entries DatabaseDescriptor.setColumnIndexCacheSize(1 << 20); diff --git a/test/unit/org/apache/cassandra/config/DataRateSpecTest.java b/test/unit/org/apache/cassandra/config/DataRateSpecTest.java index 11340b0a88..1d0d84f1bb 100644 --- a/test/unit/org/apache/cassandra/config/DataRateSpecTest.java +++ b/test/unit/org/apache/cassandra/config/DataRateSpecTest.java @@ -31,37 +31,57 @@ public class DataRateSpecTest @Test public void testConversions() { - assertEquals(10, new DataRateSpec("10B/s").toBytesPerSecond(), 0); - assertEquals(10240, new DataRateSpec("10KiB/s").toBytesPerSecond(), 0); - assertEquals(0, new DataRateSpec("10KiB/s").toMebibytesPerSecond(), 0.1); - assertEquals(10240, new DataRateSpec("10MiB/s").toKibibytesPerSecond(), 0); - assertEquals(10485760, new DataRateSpec("10MiB/s").toBytesPerSecond(), 0); - assertEquals(10485760, new DataRateSpec("10MiB/s").toBytesPerSecond(), 0); - assertEquals(new DataRateSpec("24MiB/s").toString(), DataRateSpec.megabitsPerSecondInMebibytesPerSecond(200L).toString()); + assertEquals(10, new DataRateSpec.LongBytesPerSecondBound("10B/s").toBytesPerSecond(), 0); + assertEquals(10240, new DataRateSpec.LongBytesPerSecondBound("10KiB/s").toBytesPerSecond(), 0); + assertEquals(0, new DataRateSpec.LongBytesPerSecondBound("10KiB/s").toMebibytesPerSecond(), 0.1); + assertEquals(10240, new DataRateSpec.LongBytesPerSecondBound("10MiB/s").toKibibytesPerSecond(), 0); + assertEquals(10485760, new DataRateSpec.LongBytesPerSecondBound("10MiB/s").toBytesPerSecond(), 0); + assertEquals(10485760, new DataRateSpec.LongBytesPerSecondBound("10MiB/s").toBytesPerSecond(), 0); + assertEquals(new DataRateSpec.LongBytesPerSecondBound("24MiB/s").toString(), DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(200L).toString()); + + assertEquals(10, new DataRateSpec.IntMebibytesPerSecondBound("10B/s").toBytesPerSecond(), 0); + assertEquals(10240, new DataRateSpec.IntMebibytesPerSecondBound("10KiB/s").toBytesPerSecond(), 0); + assertEquals(0, new DataRateSpec.IntMebibytesPerSecondBound("10KiB/s").toMebibytesPerSecond(), 0.1); + assertEquals(10240, new DataRateSpec.IntMebibytesPerSecondBound("10MiB/s").toKibibytesPerSecond(), 0); + assertEquals(10485760, new DataRateSpec.IntMebibytesPerSecondBound("10MiB/s").toBytesPerSecond(), 0); + assertEquals(10485760, new DataRateSpec.IntMebibytesPerSecondBound("10MiB/s").toBytesPerSecond(), 0); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s").toString(), DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(200L).toString()); } @Test public void testOverflowingDuringConversion() { - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807B/s").toBytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807B/s").toBytesPerSecondAsInt(), 0); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807KiB/s").toBytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807KiB/s").toBytesPerSecondAsInt(), 0); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toBytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toBytesPerSecondAsInt(), 0); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toBytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toBytesPerSecondAsInt(), 0); + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound("2147483649B/s").toBytesPerSecondAsInt(), 0); + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound(2147483649L / 1024L + "KiB/s").toBytesPerSecondAsInt(), 0); + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound(2147483649L / 1024L / 1024 + "MiB/s").toBytesPerSecondAsInt(), 0); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toMegabitsPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toMegabitsPerSecondAsInt()); + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound(2147483646L + "MiB/s").toMegabitsPerSecondAsInt()); + + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound(2147483647L + "KiB/s").toKibibytesPerSecondAsInt()); + assertEquals(Integer.MAX_VALUE, new DataRateSpec.IntMebibytesPerSecondBound(2147483649L / 1024L + "MiB/s").toKibibytesPerSecondAsInt()); + + assertEquals(Integer.MAX_VALUE-1, new DataRateSpec.IntMebibytesPerSecondBound(2147483646L + "MiB/s").toMebibytesPerSecondAsInt()); + + assertThatThrownBy(() -> new DataRateSpec.IntMebibytesPerSecondBound("2147483648MiB/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2147483648MiB/s. " + + "It shouldn't be more than 2147483646 in mebibytes_per_second"); + assertThatThrownBy(() -> new DataRateSpec.IntMebibytesPerSecondBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2.147483648E9 mebibytes_per_second. " + + "It shouldn't be more than 2147483646 in mebibytes_per_second"); + + assertThatThrownBy(() -> new DataRateSpec.IntMebibytesPerSecondBound((Integer.MAX_VALUE * 1024L + 1L) + "KiB/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2199023254529KiB/s. " + + "It shouldn't be more than 2147483646 in mebibytes_per_second"); + assertThatThrownBy(() -> new DataRateSpec.IntMebibytesPerSecondBound((Integer.MAX_VALUE * 1024L * 1024 + 1L) + "B/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2251799812636673B/s. " + + "It shouldn't be more than 2147483646 in mebibytes_per_second"); + assertThatThrownBy(() -> DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2147483648 megabits per second; " + + "stream_throughput_outbound and " + + "inter_dc_stream_throughput_outbound should " + + "be between 0 and 2147483647 in megabits per second"); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807KiB/s").toKibibytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807KiB/s").toKibibytesPerSecondAsInt()); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toKibibytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toKibibytesPerSecondAsInt()); - assertEquals(Long.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toMebibytesPerSecond(), 0); - assertEquals(Integer.MAX_VALUE, new DataRateSpec("9223372036854775807MiB/s").toMebibytesPerSecondAsInt()); } @Test @@ -78,38 +98,97 @@ public class DataRateSpecTest @Test public void testInvalidInputs() { - assertThatThrownBy(() -> new DataRateSpec("10")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid bit rate: 10"); - assertThatThrownBy(() -> new DataRateSpec("-10b/s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid bit rate: -10b/s"); - assertThatThrownBy(() -> new DataRateSpec("10xb/s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid bit rate: 10xb/s"); - assertThatThrownBy(() -> new DataRateSpec("9223372036854775809B/s") + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("10")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 10"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("-10b/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: -10b/s"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound(-10, DataRateSpec.DataRateUnit.BYTES_PER_SECOND)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: value must be non-negative"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("10xb/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 10xb/s"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("9223372036854775809B/s") .toBytesPerSecond()).isInstanceOf(NumberFormatException.class) .hasMessageContaining("For input string: \"9223372036854775809\""); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("9223372036854775809KiB/s") + .toBytesPerSecond()).isInstanceOf(NumberFormatException.class) + .hasMessageContaining("For input string: \"9223372036854775809\""); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound("9223372036854775809MiB/s") + .toBytesPerSecond()).isInstanceOf(NumberFormatException.class) + .hasMessageContaining("For input string: \"9223372036854775809\""); + assertThatThrownBy(() -> new DataRateSpec.IntMebibytesPerSecondBound("2147483648MiB/s") + .toBytesPerSecond()).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 2147483648MiB/s. It shouldn't be more" + + " than 2147483646 in mebibytes_per_second"); } + @Test + public void testInvalidForConversion() + { + //just test the cast to Int as currently we don't even have any long bound rates and there is a very low probability of ever having them + assertEquals(Integer.MAX_VALUE, new DataRateSpec.LongBytesPerSecondBound("92233720368547758B/s").toBytesPerSecondAsInt()); + + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound(Long.MAX_VALUE + "B/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 9223372036854775807B/s. " + + "It shouldn't be more than 9223372036854775806 in bytes_per_second"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound(Long.MAX_VALUE + "MiB/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 9223372036854775807MiB/s. " + + "It shouldn't be more than 9223372036854775806 in bytes_per_second"); + assertThatThrownBy(() -> new DataRateSpec.LongBytesPerSecondBound(Long.MAX_VALUE - 5 + "KiB/s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data rate: 9223372036854775802KiB/s. " + + "It shouldn't be more than 9223372036854775806 in bytes_per_second"); + } + + @Test + public void testValidUnits() + { + // we need toString as internally it is double and they are not 0.0 equal but for the end user the double numbers don't exist + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("24MiB/s").toString(), DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(200).toString()); + } + + @SuppressWarnings("AssertBetweenInconvertibleTypes") @Test public void testEquals() { - assertEquals(new DataRateSpec("10B/s"), new DataRateSpec("10B/s")); - assertEquals(new DataRateSpec("10KiB/s"), new DataRateSpec("10240B/s")); - assertEquals(new DataRateSpec("10240B/s"), new DataRateSpec("10KiB/s")); - assertEquals(DataRateSpec.inMebibytesPerSecond(Long.MAX_VALUE), DataRateSpec.inMebibytesPerSecond(Long.MAX_VALUE)); - assertNotEquals(DataRateSpec.inMebibytesPerSecond(Long.MAX_VALUE), DataRateSpec.inBytesPerSecond(Long.MAX_VALUE)); - assertNotEquals(new DataRateSpec("0KiB/s"), new DataRateSpec("10MiB/s")); + assertEquals(new DataRateSpec.LongBytesPerSecondBound("10B/s"), new DataRateSpec.LongBytesPerSecondBound("10B/s")); + assertEquals(new DataRateSpec.LongBytesPerSecondBound("10KiB/s"), new DataRateSpec.LongBytesPerSecondBound("10240B/s")); + assertEquals(new DataRateSpec.LongBytesPerSecondBound("10240B/s"), new DataRateSpec.LongBytesPerSecondBound("10KiB/s")); + assertNotEquals(new DataRateSpec.LongBytesPerSecondBound("0KiB/s"), new DataRateSpec.LongBytesPerSecondBound("10MiB/s")); + + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10B/s"), new DataRateSpec.IntMebibytesPerSecondBound("10B/s")); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10KiB/s"), new DataRateSpec.IntMebibytesPerSecondBound("10240B/s")); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10240B/s"), new DataRateSpec.IntMebibytesPerSecondBound("10KiB/s")); + assertNotEquals(new DataRateSpec.IntMebibytesPerSecondBound("0KiB/s"), new DataRateSpec.IntMebibytesPerSecondBound("10MiB/s")); + + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10B/s"), new DataRateSpec.LongBytesPerSecondBound("10B/s")); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10KiB/s"), new DataRateSpec.LongBytesPerSecondBound("10240B/s")); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound("10240B/s"), new DataRateSpec.LongBytesPerSecondBound("10KiB/s")); + assertNotEquals(new DataRateSpec.IntMebibytesPerSecondBound("0KiB/s"), new DataRateSpec.LongBytesPerSecondBound("10MiB/s")); } @Test - public void thereAndBack() + public void thereAndBackLongBytesPerSecondBound() { Gen unitGen = SourceDSL.arbitrary().enumValues(DataRateSpec.DataRateUnit.class); - Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE); + // DataRateSpec is a special case where we have double so we can accomodate the backward compatibility for parameters which were in + // megabits per second before without losing precision + // Extremely big numbers might be not completely accurate, that is why here Long.MAX_VALUE is not failing for bytes being >= Long.MAX_VALUE + Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE/1024L/1024L); // the biggest value in MiB/s that won't lead to B/s overflow qt().forAll(valueGen, unitGen).check((value, unit) -> { - DataRateSpec there = new DataRateSpec(value, unit); - DataRateSpec back = new DataRateSpec(there.toString()); - DataRateSpec BACK = new DataRateSpec(there.toString()); - return there.equals(back) && there.equals(BACK); + DataRateSpec.LongBytesPerSecondBound there = new DataRateSpec.LongBytesPerSecondBound(value, unit); + DataRateSpec.LongBytesPerSecondBound back = new DataRateSpec.LongBytesPerSecondBound(there.toString()); + return there.equals(back) && back.equals(there); + }); + } + + @Test + public void thereAndBackIntMebibytesPerSecondBound() + { + Gen unitGen = SourceDSL.arbitrary().enumValues(DataRateSpec.DataRateUnit.class); + Gen valueGen = SourceDSL.longs().between(0, Integer.MAX_VALUE-1); // max MiB/s + qt().forAll(valueGen, unitGen).check((value, unit) -> { + DataRateSpec.IntMebibytesPerSecondBound there = new DataRateSpec.IntMebibytesPerSecondBound(value, unit); + DataRateSpec.IntMebibytesPerSecondBound back = new DataRateSpec.IntMebibytesPerSecondBound(there.toString()); + return there.equals(back) && back.equals(there); }); } @@ -128,8 +207,8 @@ public class DataRateSpecTest private static Gen gen() { Gen unitGen = SourceDSL.arbitrary().enumValues(DataRateSpec.DataRateUnit.class); - Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE); - Gen gen = rs -> new DataRateSpec(valueGen.generate(rs), unitGen.generate(rs)); + Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE/1024L/1024/1024); + Gen gen = rs -> new DataRateSpec.LongBytesPerSecondBound(valueGen.generate(rs), unitGen.generate(rs)); return gen.describedAs(DataRateSpec::toString); } -} \ No newline at end of file +} diff --git a/test/unit/org/apache/cassandra/config/DataStorageSpecTest.java b/test/unit/org/apache/cassandra/config/DataStorageSpecTest.java index b51ce17762..334e33f259 100644 --- a/test/unit/org/apache/cassandra/config/DataStorageSpecTest.java +++ b/test/unit/org/apache/cassandra/config/DataStorageSpecTest.java @@ -24,54 +24,138 @@ import org.junit.Test; import org.quicktheories.core.Gen; import org.quicktheories.generators.SourceDSL; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.BYTES; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.GIBIBYTES; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.*; import static org.quicktheories.QuickTheory.qt; public class DataStorageSpecTest { + private static final long MAX_LONG_CONFIG_VALUE = Long.MAX_VALUE - 1; @Test public void testConversions() { - assertEquals(10, new DataStorageSpec("10B").toBytes()); - assertEquals(10240, new DataStorageSpec("10KiB").toBytes()); - assertEquals(0, new DataStorageSpec("10KiB").toMebibytes()); - assertEquals(10240, new DataStorageSpec("10MiB").toKibibytes()); - assertEquals(10485760, new DataStorageSpec("10MiB").toBytes()); + assertEquals(10, new DataStorageSpec.LongBytesBound("10B").toBytes()); + assertEquals(10240, new DataStorageSpec.LongBytesBound("10KiB").toBytes()); + assertEquals(10485760, new DataStorageSpec.LongBytesBound("10MiB").toBytes()); + assertEquals(1073741824, new DataStorageSpec.LongBytesBound("1GiB").toBytes()); + + assertEquals(1024, new DataStorageSpec.LongMebibytesBound("1GiB").toMebibytes()); + assertEquals(10485760, new DataStorageSpec.LongMebibytesBound("10MiB").toBytes()); + assertEquals(10240, new DataStorageSpec.LongMebibytesBound("10MiB").toKibibytes()); + assertEquals(1024 * 1024 * 1024, new DataStorageSpec.IntBytesBound("1GiB").toBytes()); + assertEquals(10240, new DataStorageSpec.IntKibibytesBound("10MiB").toKibibytes()); + assertEquals(1024, new DataStorageSpec.IntMebibytesBound("1GiB").toMebibytes()); + + assertEquals(10, new DataStorageSpec.LongBytesBound(10, BYTES).toBytes()); + assertEquals(10240, new DataStorageSpec.LongBytesBound(10, KIBIBYTES).toBytes()); + assertEquals(10485760, new DataStorageSpec.LongBytesBound(10, MEBIBYTES).toBytes()); + assertEquals(1073741824, new DataStorageSpec.LongBytesBound(1, GIBIBYTES).toBytes()); + + assertEquals(1024, new DataStorageSpec.LongMebibytesBound(1, GIBIBYTES).toMebibytes()); + assertEquals(1024 * 1024, new DataStorageSpec.LongMebibytesBound(1, GIBIBYTES).toKibibytes()); + assertEquals(10485760, new DataStorageSpec.LongMebibytesBound(10, MEBIBYTES).toBytes()); + assertEquals(10240, new DataStorageSpec.IntKibibytesBound(10, MEBIBYTES).toKibibytes()); + assertEquals(1024, new DataStorageSpec.IntMebibytesBound(1, GIBIBYTES).toMebibytes()); } @Test - public void testOverflowingDuringConversion() + public void testOverflowingConversion() { - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807B").toBytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807B").toBytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807KiB").toBytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807KiB").toBytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toBytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toBytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toBytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toBytesAsInt()); + assertThatThrownBy(() -> new DataStorageSpec.IntBytesBound("2147483648B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648B. " + + "It shouldn't be more than 2147483646 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntBytesBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648 bytes. " + + "It shouldn't be more than 2147483646 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntBytesBound("2147483648KiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648KiB. " + + "It shouldn't be more than 2147483646 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntBytesBound("35791395MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 35791395MiB. " + + "It shouldn't be more than 2147483646 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntBytesBound("34954GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 34954GiB. " + + "It shouldn't be more than 2147483646 in bytes"); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807KiB").toKibibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807KiB").toKibibytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toKibibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toKibibytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toKibibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toKibibytesAsInt()); + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound("2147483648B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648B " + + "Accepted units:[KIBIBYTES, MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound(2147483648L, BYTES)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648B " + + "Accepted units:[KIBIBYTES, MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound("2147483648KiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648KiB. " + + "It shouldn't be more than 2147483646 in kibibytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound("35791395MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 35791395MiB. " + + "It shouldn't be more than 2147483646 in kibibytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound("34954GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 34954GiB. " + + "It shouldn't be more than 2147483646 in kibibytes"); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toMebibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807MiB").toMebibytesAsInt()); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toMebibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toMebibytesAsInt()); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound("2147483648B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648B " + + "Accepted units:[MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound("2147483648MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648MiB. " + + "It shouldn't be more than 2147483646 in mebibytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound(2147483648L, MEBIBYTES)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648 mebibytes. " + + "It shouldn't be more than 2147483646 in mebibytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound("2097152GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2097152GiB. " + + "It shouldn't be more than 2147483646 in mebibytes"); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 2147483648 mebibytes." + + " It shouldn't be more than 2147483646 in mebibytes"); - assertEquals(Long.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toGibibytes()); - assertEquals(Integer.MAX_VALUE, new DataStorageSpec("9223372036854775807GiB").toGibibytesAsInt()); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE + "B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807B. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE, BYTES)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807 bytes. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807 bytes. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE + "KiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807KiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("9223372036854775MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775MiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("9223372036854775GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775GiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound(Long.MAX_VALUE + "B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807B " + + "Accepted units:[MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound(Long.MAX_VALUE, BYTES)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807B " + + "Accepted units:[MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound(Long.MAX_VALUE + "KiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807KiB " + + "Accepted units:[MEBIBYTES, GIBIBYTES]"); + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound(Long.MAX_VALUE + "MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807MiB. " + + "It shouldn't be more than 9223372036854775806 in mebibytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound("9223372036854775555GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775555GiB. " + + "It shouldn't be more than 9223372036854775806 in mebibytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound(Long.MAX_VALUE)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807 mebibytes." + + " It shouldn't be more than 9223372036854775806 in mebibytes"); } @Test public void testFromSymbol() { - assertEquals(DataStorageSpec.DataStorageUnit.fromSymbol("B"), DataStorageSpec.DataStorageUnit.BYTES); + assertEquals(DataStorageSpec.DataStorageUnit.fromSymbol("B"), BYTES); assertEquals(DataStorageSpec.DataStorageUnit.fromSymbol("KiB"), DataStorageSpec.DataStorageUnit.KIBIBYTES); assertEquals(DataStorageSpec.DataStorageUnit.fromSymbol("MiB"), DataStorageSpec.DataStorageUnit.MEBIBYTES); assertEquals(DataStorageSpec.DataStorageUnit.fromSymbol("GiB"), DataStorageSpec.DataStorageUnit.GIBIBYTES); @@ -83,62 +167,82 @@ public class DataStorageSpecTest @Test public void testInvalidInputs() { - assertThatThrownBy(() -> new DataStorageSpec("10")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: 10"); - assertThatThrownBy(() -> new DataStorageSpec("-10bps")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: -10bps"); - assertThatThrownBy(() -> new DataStorageSpec("-10b")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: -10b"); - assertThatThrownBy(() -> new DataStorageSpec("10HG")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: 10HG"); - assertThatThrownBy(() -> new DataStorageSpec("9223372036854775809B") + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("10")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 10"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("-10bps")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: -10bps"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("-10b")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: -10b"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(-10, BYTES)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: value must be non-negative"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("10HG")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 10HG"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound("9223372036854775809B") .toBytes()).isInstanceOf(NumberFormatException.class) .hasMessageContaining("For input string: \"9223372036854775809\""); + + assertThatThrownBy(() -> new DataStorageSpec.IntKibibytesBound("10B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 10B Accepted units"); + assertThatThrownBy(() -> new DataStorageSpec.IntMebibytesBound("10B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 10B Accepted units"); + + assertThatThrownBy(() -> new DataStorageSpec.LongMebibytesBound("10B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 10B Accepted units"); + } + + @Test + public void testValidUnits() + { + assertEquals(10240L, new DataStorageSpec.IntBytesBound("10KiB").toBytes()); + assertEquals(10L, new DataStorageSpec.IntKibibytesBound("10KiB").toKibibytes()); + assertEquals(10L, new DataStorageSpec.IntMebibytesBound("10MiB").toMebibytes()); + } + + @Test + public void testInvalidForConversion() + { + //just test the cast to Int +// assertEquals(Integer.MAX_VALUE, new DataStorageSpec.LongBytesBound("9223372036854775806B").toBytesAsInt()); + + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE + "B")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807B. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE + "KiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775807KiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE-5L + "MiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775802MiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); + assertThatThrownBy(() -> new DataStorageSpec.LongBytesBound(Long.MAX_VALUE-5L + "GiB")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid data storage: 9223372036854775802GiB. " + + "It shouldn't be more than 9223372036854775806 in bytes"); } @Test public void testEquals() { - assertEquals(new DataStorageSpec("10B"), new DataStorageSpec("10B")); + assertEquals(new DataStorageSpec.LongBytesBound("10B"), new DataStorageSpec.LongBytesBound("10B")); - assertEquals(new DataStorageSpec("10KiB"), new DataStorageSpec("10240B")); - assertEquals(new DataStorageSpec("10240B"), new DataStorageSpec("10KiB")); + assertEquals(new DataStorageSpec.LongBytesBound.LongBytesBound("10KiB"), new DataStorageSpec.LongBytesBound.LongBytesBound("10240B")); + assertEquals(new DataStorageSpec.LongBytesBound.LongBytesBound("10240B"), new DataStorageSpec.LongBytesBound("10KiB")); - assertEquals(new DataStorageSpec("10MiB"), new DataStorageSpec("10240KiB")); - assertEquals(new DataStorageSpec("10240KiB"), new DataStorageSpec("10MiB")); + assertEquals(new DataStorageSpec.LongBytesBound("10MiB"), new DataStorageSpec.LongBytesBound("10240KiB")); + assertEquals(new DataStorageSpec.LongBytesBound("10240KiB"), new DataStorageSpec.LongBytesBound("10MiB")); - assertEquals(new DataStorageSpec("10GiB"), new DataStorageSpec("10240MiB")); - assertEquals(new DataStorageSpec("10240MiB"), new DataStorageSpec("10GiB")); + assertEquals(new DataStorageSpec.LongBytesBound("10GiB"), new DataStorageSpec.LongBytesBound("10240MiB")); + assertEquals(new DataStorageSpec.LongBytesBound("10240MiB"), new DataStorageSpec.LongBytesBound("10GiB")); - assertNotEquals(DataStorageSpec.inBytes(Long.MAX_VALUE), DataStorageSpec.inGibibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inBytes(Long.MAX_VALUE), DataStorageSpec.inMebibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inBytes(Long.MAX_VALUE), DataStorageSpec.inKibibytes(Long.MAX_VALUE)); - assertEquals(DataStorageSpec.inBytes(Long.MAX_VALUE), DataStorageSpec.inBytes(Long.MAX_VALUE)); + assertEquals(new DataStorageSpec.LongBytesBound(MAX_LONG_CONFIG_VALUE, BYTES), new DataStorageSpec.LongBytesBound(MAX_LONG_CONFIG_VALUE, BYTES)); - assertNotEquals(DataStorageSpec.inKibibytes(Long.MAX_VALUE), DataStorageSpec.inGibibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inKibibytes(Long.MAX_VALUE), DataStorageSpec.inMebibytes(Long.MAX_VALUE)); - assertEquals(DataStorageSpec.inKibibytes(Long.MAX_VALUE), DataStorageSpec.inKibibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inKibibytes(Long.MAX_VALUE), DataStorageSpec.inBytes(Long.MAX_VALUE)); - - assertNotEquals(DataStorageSpec.inMebibytes(Long.MAX_VALUE), DataStorageSpec.inGibibytes(Long.MAX_VALUE)); - assertEquals(DataStorageSpec.inMebibytes(Long.MAX_VALUE), DataStorageSpec.inMebibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inMebibytes(Long.MAX_VALUE), DataStorageSpec.inBytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inMebibytes(Long.MAX_VALUE), DataStorageSpec.inBytes(Long.MAX_VALUE)); - - assertEquals(DataStorageSpec.inGibibytes(Long.MAX_VALUE), DataStorageSpec.inGibibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inGibibytes(Long.MAX_VALUE), DataStorageSpec.inMebibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inGibibytes(Long.MAX_VALUE), DataStorageSpec.inKibibytes(Long.MAX_VALUE)); - assertNotEquals(DataStorageSpec.inGibibytes(Long.MAX_VALUE), DataStorageSpec.inBytes(Long.MAX_VALUE)); - - assertNotEquals(new DataStorageSpec("0MiB"), new DataStorageSpec("10KiB")); + assertNotEquals(new DataStorageSpec.LongBytesBound("0MiB"), new DataStorageSpec.LongBytesBound("10KiB")); } @Test - public void thereAndBack() + public void thereAndBackLongBytesBound() { qt().forAll(gen()).check(there -> { - DataStorageSpec back = new DataStorageSpec(there.toString()); - DataStorageSpec BACK = new DataStorageSpec(there.toString().toUpperCase(Locale.ROOT).replace("I", "i")); + DataStorageSpec.LongBytesBound back = new DataStorageSpec.LongBytesBound(there.toString()); + DataStorageSpec.LongBytesBound BACK = new DataStorageSpec.LongBytesBound(there.toString().toUpperCase(Locale.ROOT).replace("I", "i")); return there.equals(back) && there.equals(BACK); }); } @@ -155,11 +259,11 @@ public class DataStorageSpecTest qt().forAll(gen(), gen()).check((a, b) -> !a.equals(b) || a.hashCode() == b.hashCode()); } - private static Gen gen() + private static Gen gen() { - Gen unitGen = SourceDSL.arbitrary().enumValues(DataStorageSpec.DataStorageUnit.class); - Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE); - Gen gen = rs -> new DataStorageSpec(valueGen.generate(rs), unitGen.generate(rs)); - return gen.describedAs(DataStorageSpec::toString); + Gen unitGen = SourceDSL.arbitrary().enumValues(DataStorageSpec.LongBytesBound.DataStorageUnit.class); + Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE/1024L/1024/1024); // max in GiB we can have without overflowing + Gen gen = rs -> new DataStorageSpec.LongBytesBound(valueGen.generate(rs), unitGen.generate(rs)); + return gen.describedAs(DataStorageSpec.LongBytesBound::toString); } } diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java index 1e484404b8..a4cb249ca7 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java @@ -89,26 +89,47 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.config.Config$UserFunctionTimeoutPolicy", "org.apache.cassandra.config.Config$CorruptedTombstoneStrategy", "org.apache.cassandra.config.DatabaseDescriptor$ByteUnit", - "org.apache.cassandra.config.ParameterizedClass", + "org.apache.cassandra.config.DataRateSpec", + "org.apache.cassandra.config.DataRateSpec$DataRateUnit", + "org.apache.cassandra.config.DataRateSpec$DataRateUnit$1", + "org.apache.cassandra.config.DataRateSpec$DataRateUnit$2", + "org.apache.cassandra.config.DataRateSpec$DataRateUnit$3", + "org.apache.cassandra.config.DataStorageSpec", + "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit", + "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$1", + "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$2", + "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$3", + "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$4", + "org.apache.cassandra.config.DataStorageSpec$IntBytesBound", + "org.apache.cassandra.config.DataStorageSpec$IntKibibytesBound", + "org.apache.cassandra.config.DataStorageSpec$IntMebibytesBound", + "org.apache.cassandra.config.DataStorageSpec$LongBytesBound", + "org.apache.cassandra.config.DataStorageSpec$LongMebibytesBound", + "org.apache.cassandra.config.DurationSpec", + "org.apache.cassandra.config.DataRateSpec$IntMebibytesPerSecondBound", + "org.apache.cassandra.config.DurationSpec$LongMillisecondsBound", + "org.apache.cassandra.config.DurationSpec$LongNanosecondsBound", + "org.apache.cassandra.config.DurationSpec$LongSecondsBound", + "org.apache.cassandra.config.DurationSpec$IntMillisecondsBound", + "org.apache.cassandra.config.DurationSpec$IntSecondsBound", + "org.apache.cassandra.config.DurationSpec$IntMinutesBound", "org.apache.cassandra.config.EncryptionOptions", "org.apache.cassandra.config.EncryptionOptions$ClientEncryptionOptions", "org.apache.cassandra.config.EncryptionOptions$ServerEncryptionOptions", "org.apache.cassandra.config.EncryptionOptions$ServerEncryptionOptions$InternodeEncryption", "org.apache.cassandra.config.EncryptionOptions$ServerEncryptionOptions$OutgoingEncryptedPortSource", - "org.apache.cassandra.db.guardrails.GuardrailsConfig", - "org.apache.cassandra.db.guardrails.GuardrailsConfigMBean", - "org.apache.cassandra.db.guardrails.GuardrailsConfig$ConsistencyLevels", - "org.apache.cassandra.db.guardrails.GuardrailsConfig$TableProperties", "org.apache.cassandra.config.GuardrailsOptions", "org.apache.cassandra.config.GuardrailsOptions$Config", "org.apache.cassandra.config.GuardrailsOptions$ConsistencyLevels", "org.apache.cassandra.config.GuardrailsOptions$TableProperties", + "org.apache.cassandra.config.ParameterizedClass", "org.apache.cassandra.config.ReplicaFilteringProtectionOptions", "org.apache.cassandra.config.YamlConfigurationLoader", "org.apache.cassandra.config.YamlConfigurationLoader$PropertiesChecker", "org.apache.cassandra.config.YamlConfigurationLoader$PropertiesChecker$1", "org.apache.cassandra.config.YamlConfigurationLoader$CustomConstructor", "org.apache.cassandra.config.TransparentDataEncryptionOptions", + "org.apache.cassandra.config.StartupChecksOptions", "org.apache.cassandra.config.SubnetGroups", "org.apache.cassandra.config.TrackWarnings", "org.apache.cassandra.db.ConsistencyLevel", @@ -119,6 +140,10 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.db.commitlog.CommitLogSegmentManagerStandard", "org.apache.cassandra.db.commitlog.CommitLog", "org.apache.cassandra.db.commitlog.CommitLogMBean", + "org.apache.cassandra.db.guardrails.GuardrailsConfig", + "org.apache.cassandra.db.guardrails.GuardrailsConfigMBean", + "org.apache.cassandra.db.guardrails.GuardrailsConfig$ConsistencyLevels", + "org.apache.cassandra.db.guardrails.GuardrailsConfig$TableProperties", "org.apache.cassandra.db.guardrails.Values$Config", "org.apache.cassandra.dht.IPartitioner", "org.apache.cassandra.distributed.api.IInstance", @@ -198,25 +223,7 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.ConsoleAppenderCustomizer", "org.apache.cassandra.locator.InetAddressAndPort", "org.apache.cassandra.cql3.statements.schema.AlterKeyspaceStatement", - "org.apache.cassandra.cql3.statements.schema.CreateKeyspaceStatement", - "org.apache.cassandra.config.DurationSpec", - "org.apache.cassandra.config.DataStorageSpec", - "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit", - "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$1", - "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$2", - "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$3", - "org.apache.cassandra.config.DataStorageSpec$DataStorageUnit$4", - "org.apache.cassandra.config.DataRateSpec", - "org.apache.cassandra.config.DataRateSpec$DataRateUnit", - "org.apache.cassandra.config.DataRateSpec$DataRateUnit$1", - "org.apache.cassandra.config.DataRateSpec$DataRateUnit$2", - "org.apache.cassandra.config.DataRateSpec$DataRateUnit$3", - "org.apache.cassandra.config.SmallestDurationMinutes", - "org.apache.cassandra.config.SmallestDurationSeconds", - "org.apache.cassandra.config.SmallestDurationMilliseconds", - "org.apache.cassandra.config.SmallestDataStorageKibibytes", - "org.apache.cassandra.config.SmallestDataStorageMebibytes", - "org.apache.cassandra.config.StartupChecksOptions", + "org.apache.cassandra.cql3.statements.schema.CreateKeyspaceStatement" }; static final Set checkedClasses = new HashSet<>(Arrays.asList(validClasses)); diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java index d18799d4a8..03111192a6 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorTest.java @@ -37,6 +37,7 @@ import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.exceptions.ConfigurationException; import org.assertj.core.api.Assertions; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; @@ -333,8 +334,7 @@ public class DatabaseDescriptorTest { Config testConfig = new Config(); - SmallestDurationMilliseconds greaterThanLowestTimeout = SmallestDurationMilliseconds - .inMilliseconds(DatabaseDescriptor.LOWEST_ACCEPTED_TIMEOUT.toMilliseconds() + 1); + DurationSpec.LongMillisecondsBound greaterThanLowestTimeout = new DurationSpec.LongMillisecondsBound(DatabaseDescriptor.LOWEST_ACCEPTED_TIMEOUT.toMilliseconds() + 1); testConfig.read_request_timeout = greaterThanLowestTimeout; testConfig.range_request_timeout = greaterThanLowestTimeout; @@ -353,7 +353,7 @@ public class DatabaseDescriptorTest assertEquals(testConfig.request_timeout, greaterThanLowestTimeout); //set less than Lowest acceptable value - SmallestDurationMilliseconds lowerThanLowestTimeout = SmallestDurationMilliseconds.inMilliseconds(DatabaseDescriptor.LOWEST_ACCEPTED_TIMEOUT.toMilliseconds() - 1); + DurationSpec.LongMillisecondsBound lowerThanLowestTimeout = new DurationSpec.LongMillisecondsBound(DatabaseDescriptor.LOWEST_ACCEPTED_TIMEOUT.toMilliseconds() - 1); testConfig.read_request_timeout = lowerThanLowestTimeout; testConfig.range_request_timeout = lowerThanLowestTimeout; @@ -625,8 +625,8 @@ public class DatabaseDescriptorTest public void testClientLargeReadWarnGreaterThanAbort() { Config conf = new Config(); - conf.coordinator_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.coordinator_read_size_fail_threshold = DataStorageSpec.inKibibytes(1); + conf.coordinator_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.coordinator_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(1, KIBIBYTES); Assertions.assertThatThrownBy(() -> DatabaseDescriptor.applyReadThresholdsValidations(conf)) .isInstanceOf(ConfigurationException.class) .hasMessage("coordinator_read_size_fail_threshold (1KiB) must be greater than or equal to coordinator_read_size_warn_threshold (2KiB)"); @@ -636,8 +636,8 @@ public class DatabaseDescriptorTest public void testClientLargeReadWarnEqAbort() { Config conf = new Config(); - conf.coordinator_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.coordinator_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.coordinator_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.coordinator_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -645,7 +645,7 @@ public class DatabaseDescriptorTest public void testClientLargeReadWarnEnabledAbortDisabled() { Config conf = new Config(); - conf.coordinator_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); + conf.coordinator_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); conf.coordinator_read_size_fail_threshold = null; DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -654,8 +654,8 @@ public class DatabaseDescriptorTest public void testClientLargeReadAbortEnabledWarnDisabled() { Config conf = new Config(); - conf.coordinator_read_size_warn_threshold = DataStorageSpec.inKibibytes(0); - conf.coordinator_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.coordinator_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(0, KIBIBYTES); + conf.coordinator_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -665,8 +665,8 @@ public class DatabaseDescriptorTest public void testLocalLargeReadWarnGreaterThanAbort() { Config conf = new Config(); - conf.local_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.local_read_size_fail_threshold = DataStorageSpec.inKibibytes(1); + conf.local_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.local_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(1, KIBIBYTES); Assertions.assertThatThrownBy(() -> DatabaseDescriptor.applyReadThresholdsValidations(conf)) .isInstanceOf(ConfigurationException.class) .hasMessage("local_read_size_fail_threshold (1KiB) must be greater than or equal to local_read_size_warn_threshold (2KiB)"); @@ -676,8 +676,8 @@ public class DatabaseDescriptorTest public void testLocalLargeReadWarnEqAbort() { Config conf = new Config(); - conf.local_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.local_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.local_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.local_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -685,7 +685,7 @@ public class DatabaseDescriptorTest public void testLocalLargeReadWarnEnabledAbortDisabled() { Config conf = new Config(); - conf.local_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); + conf.local_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); conf.local_read_size_fail_threshold = null; DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -694,8 +694,8 @@ public class DatabaseDescriptorTest public void testLocalLargeReadAbortEnabledWarnDisabled() { Config conf = new Config(); - conf.local_read_size_warn_threshold = DataStorageSpec.inKibibytes(0); - conf.local_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.local_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(0, KIBIBYTES); + conf.local_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -705,8 +705,8 @@ public class DatabaseDescriptorTest public void testRowIndexSizeWarnGreaterThanAbort() { Config conf = new Config(); - conf.row_index_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.row_index_read_size_fail_threshold = DataStorageSpec.inKibibytes(1); + conf.row_index_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.row_index_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(1, KIBIBYTES); Assertions.assertThatThrownBy(() -> DatabaseDescriptor.applyReadThresholdsValidations(conf)) .isInstanceOf(ConfigurationException.class) .hasMessage("row_index_read_size_fail_threshold (1KiB) must be greater than or equal to row_index_read_size_warn_threshold (2KiB)"); @@ -716,8 +716,8 @@ public class DatabaseDescriptorTest public void testRowIndexSizeWarnEqAbort() { Config conf = new Config(); - conf.row_index_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); - conf.row_index_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.row_index_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); + conf.row_index_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -725,7 +725,7 @@ public class DatabaseDescriptorTest public void testRowIndexSizeWarnEnabledAbortDisabled() { Config conf = new Config(); - conf.row_index_read_size_warn_threshold = DataStorageSpec.inKibibytes(2); + conf.row_index_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); conf.row_index_read_size_fail_threshold = null; DatabaseDescriptor.applyReadThresholdsValidations(conf); } @@ -734,8 +734,8 @@ public class DatabaseDescriptorTest public void testRowIndexSizeAbortEnabledWarnDisabled() { Config conf = new Config(); - conf.row_index_read_size_warn_threshold = DataStorageSpec.inKibibytes(0); - conf.row_index_read_size_fail_threshold = DataStorageSpec.inKibibytes(2); + conf.row_index_read_size_warn_threshold = new DataStorageSpec.LongBytesBound(0, KIBIBYTES); + conf.row_index_read_size_fail_threshold = new DataStorageSpec.LongBytesBound(2, KIBIBYTES); DatabaseDescriptor.applyReadThresholdsValidations(conf); } diff --git a/test/unit/org/apache/cassandra/config/DurationSpecTest.java b/test/unit/org/apache/cassandra/config/DurationSpecTest.java index 004ab421e8..22846fc701 100644 --- a/test/unit/org/apache/cassandra/config/DurationSpecTest.java +++ b/test/unit/org/apache/cassandra/config/DurationSpecTest.java @@ -24,28 +24,31 @@ import org.junit.Test; import org.quicktheories.core.Gen; import org.quicktheories.generators.SourceDSL; +import static java.util.concurrent.TimeUnit.MICROSECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.*; import static org.quicktheories.QuickTheory.qt; public class DurationSpecTest { + private static final long MAX_INT_CONFIG_VALUE = Integer.MAX_VALUE - 1; + + @SuppressWarnings("AssertBetweenInconvertibleTypes") @Test public void testConversions() { - assertEquals(10L, new DurationSpec("10s").toSeconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toSecondsAsInt()); - assertEquals(10000, new DurationSpec("10s").toMilliseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toMillisecondsAsInt()); - assertEquals(0, new DurationSpec("10s").toMinutes()); - assertEquals(10, new DurationSpec("10m").toMinutes()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toMinutesAsInt()); - assertEquals(600000, new DurationSpec("10m").toMilliseconds()); - assertEquals(600, new DurationSpec("10m").toSeconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toSecondsAsInt()); - assertEquals(DurationSpec.inDoubleMilliseconds(0.7), new DurationSpec("1ms")); - assertEquals(DurationSpec.inDoubleMilliseconds(0.33), new DurationSpec("0ms")); - assertEquals(DurationSpec.inDoubleMilliseconds(0.333), new DurationSpec("0ms")); + assertEquals(10000000000L, new DurationSpec.LongNanosecondsBound ("10s").toNanoseconds()); + assertEquals(MAX_INT_CONFIG_VALUE, new DurationSpec.IntSecondsBound(MAX_INT_CONFIG_VALUE + "s").toSeconds()); + assertEquals(MAX_INT_CONFIG_VALUE, new DurationSpec.LongMillisecondsBound(MAX_INT_CONFIG_VALUE + "ms").toMilliseconds()); + assertEquals(600000000000L, new DurationSpec.LongNanosecondsBound ("10m").toNanoseconds()); + assertEquals(MAX_INT_CONFIG_VALUE, new DurationSpec.IntMinutesBound(MAX_INT_CONFIG_VALUE + "m").toMinutes()); + assertEquals(MAX_INT_CONFIG_VALUE, new DurationSpec.IntSecondsBound(MAX_INT_CONFIG_VALUE + "s").toSeconds()); + assertEquals(new DurationSpec.IntMillisecondsBound(0.7, TimeUnit.MILLISECONDS), new DurationSpec.LongNanosecondsBound("1ms")); + assertEquals(new DurationSpec.IntMillisecondsBound(0.33, TimeUnit.MILLISECONDS), new DurationSpec.LongNanosecondsBound("0ms")); + assertEquals(new DurationSpec.IntMillisecondsBound(0.333, TimeUnit.MILLISECONDS), new DurationSpec.LongNanosecondsBound("0ms")); } @Test @@ -58,102 +61,259 @@ public class DurationSpecTest assertEquals(DurationSpec.fromSymbol("s"), TimeUnit.SECONDS); assertEquals(DurationSpec.fromSymbol("us"), TimeUnit.MICROSECONDS); assertEquals(DurationSpec.fromSymbol("µs"), TimeUnit.MICROSECONDS); - assertEquals(DurationSpec.fromSymbol("ns"), TimeUnit.NANOSECONDS); - assertThatThrownBy(() -> DurationSpec.fromSymbol("n")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Unsupported time unit: n"); + assertEquals(DurationSpec.fromSymbol("ns"), NANOSECONDS); + assertThatThrownBy(() -> DurationSpec.fromSymbol("n")).isInstanceOf(IllegalArgumentException.class); } @Test public void testGetSymbol() { - assertEquals(DurationSpec.getSymbol(TimeUnit.MILLISECONDS), "ms"); - assertEquals(DurationSpec.getSymbol(TimeUnit.DAYS), "d"); - assertEquals(DurationSpec.getSymbol(TimeUnit.HOURS), "h"); - assertEquals(DurationSpec.getSymbol(TimeUnit.MINUTES), "m"); - assertEquals(DurationSpec.getSymbol(TimeUnit.SECONDS), "s"); - assertEquals(DurationSpec.getSymbol(TimeUnit.MICROSECONDS), "us"); - assertEquals(DurationSpec.getSymbol(TimeUnit.NANOSECONDS), "ns"); + assertEquals(DurationSpec.symbol(TimeUnit.MILLISECONDS), "ms"); + assertEquals(DurationSpec.symbol(TimeUnit.DAYS), "d"); + assertEquals(DurationSpec.symbol(TimeUnit.HOURS), "h"); + assertEquals(DurationSpec.symbol(TimeUnit.MINUTES), "m"); + assertEquals(DurationSpec.symbol(TimeUnit.SECONDS), "s"); + assertEquals(DurationSpec.symbol(TimeUnit.MICROSECONDS), "us"); + assertEquals(DurationSpec.symbol(NANOSECONDS), "ns"); } @Test public void testInvalidInputs() { - assertThatThrownBy(() -> new DurationSpec("10")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10"); - assertThatThrownBy(() -> new DurationSpec("-10s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: -10s"); - assertThatThrownBy(() -> new DurationSpec("10xd")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10xd"); - assertThatThrownBy(() -> new DurationSpec("0.333555555ms")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 0.333555555ms"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound("10")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(-10, SECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: value must be non-negativ"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound("10xd")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10xd"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound("0.333555555ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 0.333555555ms"); } + @Test + public void testInvalidForConversion() + { + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE + "ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775807ns. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE + "ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775807ms. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE-5 + "µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775802µs. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE-5 + "us")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775802us. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE-5 + "s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775802s. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE-5 + "h")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775802h. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + assertThatThrownBy(() -> new DurationSpec.LongNanosecondsBound(Long.MAX_VALUE-5 + "d")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 9223372036854775802d. " + + "It shouldn't be more than 9223372036854775806 in nanoseconds"); + } + + @Test + public void testOverflowingConversion() + { + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("2147483648ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648ms." + + " It shouldn't be more than 2147483646 in milliseconds"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648 milliseconds. " + + "It shouldn't be more than 2147483646 in milliseconds"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("2147483648s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648s. " + + "It shouldn't be more than 2147483646 in milliseconds"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("35791395m")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 35791395m. " + + "It shouldn't be more than 2147483646 in milliseconds"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("597h")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 597h. " + + "It shouldn't be more than 2147483646 in milliseconds"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("24856d")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 24856d. " + + "It shouldn't be more than 2147483646 in milliseconds"); + + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("2147483648s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648s. " + + "It shouldn't be more than 2147483646 in seconds"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648 seconds. " + + "It shouldn't be more than 2147483646 in seconds"); + assertThatThrownBy(() -> DurationSpec.IntSecondsBound.inSecondsString("2147483648")).isInstanceOf(NumberFormatException.class) + .hasMessageContaining("For input string: \"2147483648\""); + assertThatThrownBy(() -> DurationSpec.IntSecondsBound.inSecondsString("2147483648s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648s. " + + "It shouldn't be more than 2147483646 in seconds"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("35791395m")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 35791395m. " + + "It shouldn't be more than 2147483646 in seconds"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("596524h")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 596524h. " + + "It shouldn't be more than 2147483646 in seconds"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("24856d")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 24856d. " + + "It shouldn't be more than 2147483646 in seconds"); + + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("2147483648s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648s " + + "Accepted units:[MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("2147483648m")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648m. " + + "It shouldn't be more than 2147483646 in minutes"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("35791395h")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 35791395h. " + + "It shouldn't be more than 2147483646 in minutes"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("1491309d")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 1491309d. " + + "It shouldn't be more than 2147483646 in minutes"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(2147483648L)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 2147483648 minutes. " + + "It shouldn't be more than 2147483646 in minutes"); + } + + @SuppressWarnings("AssertBetweenInconvertibleTypes") @Test public void testEquals() { - assertEquals(new DurationSpec("10s"), new DurationSpec("10s")); - assertEquals(new DurationSpec("10s"), new DurationSpec("10000ms")); - assertEquals(new DurationSpec("10000ms"), new DurationSpec("10s")); - assertEquals(DurationSpec.inMinutes(Long.MAX_VALUE), DurationSpec.inMinutes(Long.MAX_VALUE)); - assertEquals(new DurationSpec("4h"), new DurationSpec("14400s")); - assertEquals(DurationSpec.inSecondsString("14400"), new DurationSpec("14400s")); - assertEquals(DurationSpec.inSecondsString("4h"), new DurationSpec("14400s")); - assertEquals(DurationSpec.inSecondsString("14400s"), new DurationSpec("14400s")); - assertEquals(DurationSpec.inHours(Long.MAX_VALUE),DurationSpec.inHours(Long.MAX_VALUE)); - assertNotEquals(DurationSpec.inMinutes(Long.MAX_VALUE), DurationSpec.inMilliseconds(Long.MAX_VALUE)); - assertNotEquals(new DurationSpec("0m"), new DurationSpec("10ms")); + assertEquals(new DurationSpec.LongNanosecondsBound ("10s"), new DurationSpec.LongNanosecondsBound ("10s")); + assertEquals(new DurationSpec.LongNanosecondsBound ("10s"), new DurationSpec.LongNanosecondsBound ("10000ms")); + assertEquals(new DurationSpec.LongNanosecondsBound ("10000ms"), new DurationSpec.LongNanosecondsBound ("10s")); + assertEquals(new DurationSpec.LongNanosecondsBound ("4h"), new DurationSpec.LongNanosecondsBound ("14400s")); + assertEquals(DurationSpec.LongNanosecondsBound .IntSecondsBound.inSecondsString("14400"), new DurationSpec.LongNanosecondsBound ("14400s")); + assertEquals(DurationSpec.LongNanosecondsBound .IntSecondsBound.inSecondsString("4h"), new DurationSpec.LongNanosecondsBound ("14400s")); + assertEquals(DurationSpec.LongNanosecondsBound .IntSecondsBound.inSecondsString("14400s"), new DurationSpec.LongNanosecondsBound ("14400s")); + assertNotEquals(new DurationSpec.LongNanosecondsBound ("0m"), new DurationSpec.LongNanosecondsBound ("10ms")); + assertEquals(Long.MAX_VALUE-1, new DurationSpec.LongNanosecondsBound ("9223372036854775806ns").toNanoseconds()); } @Test public void thereAndBack() { Gen unitGen = SourceDSL.arbitrary().enumValues(TimeUnit.class); - Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE); + Gen valueGen = SourceDSL.longs().between(0, Long.MAX_VALUE/24/60/60/1000L/1000L/1000L); qt().forAll(valueGen, unitGen).check((value, unit) -> { - DurationSpec there = new DurationSpec(value, unit); - DurationSpec back = new DurationSpec(there.toString()); + DurationSpec.LongNanosecondsBound there = new DurationSpec.LongNanosecondsBound (value, unit); + DurationSpec.LongNanosecondsBound back = new DurationSpec.LongNanosecondsBound (there.toString()); return there.equals(back); }); } @Test - public void testOverflowingDuringConversion() + public void testValidUnits() { - // we are heavily dependent on the Java TimeUnit for our configuration of type duration. We want to be sure - // that any regression in handlining overflow will be caught quickly on our end - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807ns").toNanoseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807ns").toNanosecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807ms").toNanoseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807ms").toNanosecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807s").toNanoseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toNanosecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807m").toNanoseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807m").toNanosecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807h").toNanoseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807h").toNanosecondsAsInt()); + assertEquals(10L, new DurationSpec.IntMillisecondsBound("10ms").toMilliseconds()); + assertEquals(10L, new DurationSpec.IntSecondsBound("10s").toSeconds()); + assertEquals(new DurationSpec.IntSecondsBound("10s"), DurationSpec.IntSecondsBound.inSecondsString("10")); + assertEquals(new DurationSpec.IntSecondsBound("10s"), DurationSpec.IntSecondsBound.inSecondsString("10s")); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807ms").toMilliseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807ms").toMillisecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807s").toMilliseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toMillisecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807m").toMilliseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807m").toMillisecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807h").toMilliseconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807h").toMillisecondsAsInt()); - - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807s").toSeconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807s").toSecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807m").toSeconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807m").toSecondsAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807h").toSeconds()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807h").toSecondsAsInt()); - - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807m").toMinutes()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807m").toMinutesAsInt()); - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807h").toMinutes()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807h").toMinutesAsInt()); - - assertEquals(Long.MAX_VALUE, new DurationSpec("9223372036854775807h").toHours()); - assertEquals(Integer.MAX_VALUE, new DurationSpec("9223372036854775807h").toHoursAsInt()); + assertEquals(10L, new DurationSpec.LongMillisecondsBound("10ms").toMilliseconds()); + assertEquals(10L, new DurationSpec.LongSecondsBound("10s").toSeconds()); } -} \ No newline at end of file + + @Test + public void testInvalidUnits() + { + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("10ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ns " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound(10, NANOSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 NANOSECONDS " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("10us")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10us " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("10µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10µs " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + assertThatThrownBy(() -> new DurationSpec.IntMillisecondsBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s " + + "Accepted units:[MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]"); + + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("10ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ms Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound(10, MILLISECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MILLISECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("10ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ns Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound(10, NANOSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 NANOSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("10us")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10us Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("10µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10µs Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntSecondsBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s"); + + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10s Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(10, SECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 SECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("10ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ms Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(10, MILLISECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MILLISECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("10ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ns Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(10, NANOSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 NANOSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("10us")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10us Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("10µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10µs Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.IntMinutesBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s"); + + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound("10ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ns Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound(10, NANOSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 NANOSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound("10us")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10us Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound("10µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10µs Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongMillisecondsBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s"); + + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound("10ms")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ms Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound(10, MILLISECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MILLISECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound("10ns")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10ns Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound(10, NANOSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 NANOSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound("10µs")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10µs Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound(10, MICROSECONDS)).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: 10 MICROSECONDS Accepted units"); + assertThatThrownBy(() -> new DurationSpec.LongSecondsBound("-10s")).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Invalid duration: -10s"); + } +} diff --git a/test/unit/org/apache/cassandra/config/LoadOldYAMLBackwardCompatibilityTest.java b/test/unit/org/apache/cassandra/config/LoadOldYAMLBackwardCompatibilityTest.java index 997d98255c..5c71cc02f5 100644 --- a/test/unit/org/apache/cassandra/config/LoadOldYAMLBackwardCompatibilityTest.java +++ b/test/unit/org/apache/cassandra/config/LoadOldYAMLBackwardCompatibilityTest.java @@ -18,6 +18,8 @@ package org.apache.cassandra.config; +import java.util.concurrent.TimeUnit; + import org.junit.BeforeClass; import org.junit.Test; @@ -41,66 +43,66 @@ public class LoadOldYAMLBackwardCompatibilityTest { Config config = DatabaseDescriptor.loadConfig(); - assertEquals(DurationSpec.inMilliseconds(10800000), config.max_hint_window); - assertEquals(DurationSpec.inHours(3), config.max_hint_window); - assertEquals(DurationSpec.inMilliseconds(0), config.native_transport_idle_timeout); - assertEquals(DurationSpec.inMilliseconds(10000), config.request_timeout); - assertEquals(DurationSpec.inMilliseconds(5000), config.read_request_timeout); - assertEquals(DurationSpec.inMilliseconds(10000), config.range_request_timeout); - assertEquals(DurationSpec.inMilliseconds(2000), config.write_request_timeout); - assertEquals(DurationSpec.inMilliseconds(5000), config.counter_write_request_timeout); - assertEquals(DurationSpec.inMilliseconds(1800), config.cas_contention_timeout); - assertEquals(DurationSpec.inMilliseconds(60000), config.truncate_request_timeout); - assertEquals(DurationSpec.inSeconds(300), config.streaming_keep_alive_period); - assertEquals(DurationSpec.inMilliseconds(500), config.slow_query_log_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(10800000), config.max_hint_window); + assertEquals(new DurationSpec.IntMillisecondsBound("3h"), config.max_hint_window); + assertEquals(new DurationSpec.LongMillisecondsBound(0), config.native_transport_idle_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(10000), config.request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(5000), config.read_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(10000), config.range_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(2000), config.write_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(5000), config.counter_write_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(1800), config.cas_contention_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(60000), config.truncate_request_timeout); + assertEquals(new DurationSpec.IntSecondsBound(300), config.streaming_keep_alive_period); + assertEquals(new DurationSpec.LongMillisecondsBound(500), config.slow_query_log_timeout); assertNull(config.memtable_heap_space); assertNull(config.memtable_offheap_space); assertNull( config.repair_session_space); - assertEquals(DataStorageSpec.inBytes(4194304), config.internode_application_send_queue_capacity); - assertEquals(DataStorageSpec.inBytes(134217728), config.internode_application_send_queue_reserve_endpoint_capacity); - assertEquals(DataStorageSpec.inBytes(536870912), config.internode_application_send_queue_reserve_global_capacity); - assertEquals(DataStorageSpec.inBytes(4194304), config.internode_application_receive_queue_capacity); - assertEquals(DataStorageSpec.inBytes(134217728), config.internode_application_receive_queue_reserve_endpoint_capacity); - assertEquals(DataStorageSpec.inBytes(536870912), config.internode_application_receive_queue_reserve_global_capacity); - assertEquals(DurationSpec.inMilliseconds(2000), config.internode_tcp_connect_timeout); - assertEquals(DurationSpec.inMilliseconds(30000), config.internode_tcp_user_timeout); - assertEquals(DurationSpec.inMilliseconds(300000), config.internode_streaming_tcp_user_timeout); - assertEquals(DataStorageSpec.inMebibytes(16), config.native_transport_max_frame_size); - assertEquals(DataStorageSpec.inMebibytes(256), config.max_value_size); - assertEquals(DataStorageSpec.inKibibytes(4), config.column_index_size); - assertEquals(DataStorageSpec.inKibibytes(2), config.column_index_cache_size); - assertEquals(DataStorageSpec.inKibibytes(5), config.batch_size_warn_threshold); - assertEquals(DataRateSpec.inMebibytesPerSecond(64), config.compaction_throughput); - assertEquals(DataStorageSpec.inMebibytes(50), config.min_free_space_per_drive); - assertEquals(DataRateSpec.inMebibytesPerSecond(23841858).toString(), config.stream_throughput_outbound.toString()); - assertEquals(DataRateSpec.megabitsPerSecondInMebibytesPerSecond(200000000).toString(), config.stream_throughput_outbound.toString()); - assertEquals(DataRateSpec.inMebibytesPerSecond(24), config.inter_dc_stream_throughput_outbound); + assertEquals(new DataStorageSpec.IntBytesBound(4194304), config.internode_application_send_queue_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(134217728), config.internode_application_send_queue_reserve_endpoint_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(536870912), config.internode_application_send_queue_reserve_global_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(4194304), config.internode_application_receive_queue_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(134217728), config.internode_application_receive_queue_reserve_endpoint_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(536870912), config.internode_application_receive_queue_reserve_global_capacity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.internode_tcp_connect_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(30000), config.internode_tcp_user_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(300000), config.internode_streaming_tcp_user_timeout); + assertEquals(new DataStorageSpec.IntMebibytesBound(16), config.native_transport_max_frame_size); + assertEquals(new DataStorageSpec.IntMebibytesBound(256), config.max_value_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(4), config.column_index_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(2), config.column_index_cache_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(5), config.batch_size_warn_threshold); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(64), config.compaction_throughput); + assertEquals(new DataStorageSpec.IntMebibytesBound(50), config.min_free_space_per_drive); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(23841858).toString(), config.stream_throughput_outbound.toString()); + assertEquals(DataRateSpec.IntMebibytesPerSecondBound.megabitsPerSecondInMebibytesPerSecond(200000000).toString(), config.stream_throughput_outbound.toString()); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(24), config.inter_dc_stream_throughput_outbound); assertNull(config.commitlog_total_space); - assertEquals(DurationSpec.inDoubleMilliseconds(0), config.commitlog_sync_group_window); - assertEquals(DurationSpec.inMilliseconds(0), config.commitlog_sync_period); - assertEquals(DataStorageSpec.inMebibytes(5), config.commitlog_segment_size); + assertEquals(new DurationSpec.IntMillisecondsBound(0.0, TimeUnit.MILLISECONDS), config.commitlog_sync_group_window); + assertEquals(new DurationSpec.IntMillisecondsBound(0), config.commitlog_sync_period); + assertEquals(new DataStorageSpec.IntMebibytesBound(5), config.commitlog_segment_size); assertNull(config.periodic_commitlog_sync_lag_block); //Integer assertNull(config.max_mutation_size); - assertEquals(DataStorageSpec.inMebibytes(0), config.cdc_total_space); - assertEquals(DurationSpec.inMilliseconds(250), config.cdc_free_space_check_interval); - assertEquals(DurationSpec.inMilliseconds(100), config.dynamic_snitch_update_interval); - assertEquals(DurationSpec.inMilliseconds(600000), config.dynamic_snitch_reset_interval); - assertEquals(DataStorageSpec.inKibibytes(1024), config.hinted_handoff_throttle); - assertEquals(DataStorageSpec.inKibibytes(1024), config.batchlog_replay_throttle); - assertEquals(DurationSpec.inMilliseconds(10000), config.hints_flush_period); - assertEquals(DataStorageSpec.inMebibytes(128), config.max_hints_file_size); - assertEquals(DataStorageSpec.inKibibytes(10240), config.trickle_fsync_interval); - assertEquals(DataStorageSpec.inMebibytes(50), config.sstable_preemptive_open_interval); + assertEquals(new DataStorageSpec.IntMebibytesBound(0), config.cdc_total_space); + assertEquals(new DurationSpec.IntMillisecondsBound(250), config.cdc_free_space_check_interval); + assertEquals(new DurationSpec.IntMillisecondsBound(100), config.dynamic_snitch_update_interval); + assertEquals(new DurationSpec.IntMillisecondsBound(600000), config.dynamic_snitch_reset_interval); + assertEquals(new DataStorageSpec.IntKibibytesBound(1024), config.hinted_handoff_throttle); + assertEquals(new DataStorageSpec.IntKibibytesBound(1024), config.batchlog_replay_throttle); + assertEquals(new DurationSpec.IntMillisecondsBound(10000), config.hints_flush_period); + assertEquals(new DataStorageSpec.IntMebibytesBound(128), config.max_hints_file_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(10240), config.trickle_fsync_interval); + assertEquals(new DataStorageSpec.IntMebibytesBound(50), config.sstable_preemptive_open_interval); assertNull( config.key_cache_size); - assertEquals(DataStorageSpec.inMebibytes(16), config.row_cache_size); + assertEquals(new DataStorageSpec.LongMebibytesBound(16), config.row_cache_size); assertNull(config.counter_cache_size); assertNull(config.networking_cache_size); assertNull(config.file_cache_size); assertNull(config.index_summary_capacity); - assertEquals(DurationSpec.inMilliseconds(200), config.gc_log_threshold); - assertEquals(DurationSpec.inMilliseconds(1000), config.gc_warn_threshold); - assertEquals(DurationSpec.inSeconds(86400), config.trace_type_query_ttl); - assertEquals(DurationSpec.inSeconds(604800), config.trace_type_repair_ttl); + assertEquals(new DurationSpec.IntMillisecondsBound(200), config.gc_log_threshold); + assertEquals(new DurationSpec.IntMillisecondsBound(1000), config.gc_warn_threshold); + assertEquals(new DurationSpec.IntSecondsBound(86400), config.trace_type_query_ttl); + assertEquals(new DurationSpec.IntSecondsBound(604800), config.trace_type_repair_ttl); assertNull(config.prepared_statements_cache_size); assertTrue(config.user_defined_functions_enabled); assertTrue(config.scripted_user_defined_functions_enabled); @@ -109,21 +111,21 @@ public class LoadOldYAMLBackwardCompatibilityTest assertTrue(config.sasi_indexes_enabled); assertTrue(config.drop_compact_storage_enabled); assertTrue(config.user_defined_functions_threads_enabled); - assertEquals(DurationSpec.inMilliseconds(2000), config.permissions_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.permissions_validity); assertNull(config.permissions_update_interval); - assertEquals(DurationSpec.inMilliseconds(2000), config.roles_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.roles_validity); assertNull(config.roles_update_interval); - assertEquals(DurationSpec.inMilliseconds(2000), config.credentials_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.credentials_validity); assertNull(config.credentials_update_interval); - assertEquals(DurationSpec.inMinutes(60), config.index_summary_resize_interval); + assertEquals(new DurationSpec.IntMinutesBound(60), config.index_summary_resize_interval); //parameters which names have not changed with CASSANDRA-15234 - assertEquals(DurationSpec.inSecondsString("14400"), config.key_cache_save_period); - assertEquals(DurationSpec.inSecondsString("14400s"), config.key_cache_save_period); - assertEquals(DurationSpec.inHours(4), config.key_cache_save_period); - assertEquals(DurationSpec.inSecondsString("0"), config.row_cache_save_period); - assertEquals(DurationSpec.inSeconds(0), config.row_cache_save_period); - assertEquals(DurationSpec.inHours(2), config.counter_cache_save_period); - assertEquals(DurationSpec.inSeconds(35), config.cache_load_timeout); + assertEquals(DurationSpec.IntSecondsBound.inSecondsString("14400"), config.key_cache_save_period); + assertEquals(DurationSpec.IntSecondsBound.inSecondsString("14400s"), config.key_cache_save_period); + assertEquals(new DurationSpec.IntSecondsBound(4, TimeUnit.HOURS), config.key_cache_save_period); + assertEquals(DurationSpec.IntSecondsBound.inSecondsString("0"), config.row_cache_save_period); + assertEquals(new DurationSpec.IntSecondsBound(0), config.row_cache_save_period); + assertEquals(new DurationSpec.IntSecondsBound(2, TimeUnit.HOURS), config.counter_cache_save_period); + assertEquals(new DurationSpec.IntSecondsBound(35), config.cache_load_timeout); } } diff --git a/test/unit/org/apache/cassandra/config/ParseAndConvertUnitsTest.java b/test/unit/org/apache/cassandra/config/ParseAndConvertUnitsTest.java index 93895b1254..a4a818a1b2 100644 --- a/test/unit/org/apache/cassandra/config/ParseAndConvertUnitsTest.java +++ b/test/unit/org/apache/cassandra/config/ParseAndConvertUnitsTest.java @@ -20,6 +20,7 @@ package org.apache.cassandra.config; import org.junit.BeforeClass; import org.junit.Test; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.MEBIBYTES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -38,81 +39,81 @@ public class ParseAndConvertUnitsTest Config config = DatabaseDescriptor.loadConfig(); //Confirm duration parameters were successfully parsed with the default values in cassandra.yaml - assertEquals(DurationSpec.inMilliseconds(10800000), config.max_hint_window); - assertEquals(DurationSpec.inMilliseconds(0), config.native_transport_idle_timeout); - assertEquals(DurationSpec.inMilliseconds(10000), config.request_timeout); - assertEquals(DurationSpec.inMilliseconds(5000), config.read_request_timeout); - assertEquals(DurationSpec.inMilliseconds(10000), config.range_request_timeout); - assertEquals(DurationSpec.inMilliseconds(2000), config.write_request_timeout); - assertEquals(DurationSpec.inMilliseconds(5000), config.counter_write_request_timeout); - assertEquals(DurationSpec.inMilliseconds(1800), config.cas_contention_timeout); - assertEquals(DurationSpec.inMilliseconds(60000), config.truncate_request_timeout); - assertEquals(DurationSpec.inSeconds(300), config.streaming_keep_alive_period); - assertEquals(DurationSpec.inMilliseconds(500), config.slow_query_log_timeout); - assertEquals(DurationSpec.inMilliseconds(2000), config.internode_tcp_connect_timeout); - assertEquals(DurationSpec.inMilliseconds(30000), config.internode_tcp_user_timeout); - assertEquals(DurationSpec.inMilliseconds(0), config.commitlog_sync_group_window); - assertEquals(DurationSpec.inMilliseconds(0), config.commitlog_sync_period); + assertEquals(new DurationSpec.IntMillisecondsBound(10800000), config.max_hint_window); + assertEquals(new DurationSpec.LongMillisecondsBound(0), config.native_transport_idle_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(10000), config.request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(5000), config.read_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(10000), config.range_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(2000), config.write_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(5000), config.counter_write_request_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(1800), config.cas_contention_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(60000), config.truncate_request_timeout); + assertEquals(new DurationSpec.IntSecondsBound(300), config.streaming_keep_alive_period); + assertEquals(new DurationSpec.LongMillisecondsBound(500), config.slow_query_log_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.internode_tcp_connect_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(30000), config.internode_tcp_user_timeout); + assertEquals(new DurationSpec.IntMillisecondsBound(0), config.commitlog_sync_group_window); + assertEquals(new DurationSpec.IntMillisecondsBound(0), config.commitlog_sync_period); assertNull(config.periodic_commitlog_sync_lag_block); - assertEquals(DurationSpec.inMilliseconds(250), config.cdc_free_space_check_interval); - assertEquals(DurationSpec.inMilliseconds(100), config.dynamic_snitch_update_interval); - assertEquals(DurationSpec.inMilliseconds(600000), config.dynamic_snitch_reset_interval); - assertEquals(DurationSpec.inMilliseconds(200), config.gc_log_threshold); - assertEquals(DurationSpec.inMilliseconds(10000), config.hints_flush_period); - assertEquals(DurationSpec.inMilliseconds(1000), config.gc_warn_threshold); - assertEquals(DurationSpec.inSeconds(86400), config.trace_type_query_ttl); - assertEquals(DurationSpec.inSeconds(604800), config.trace_type_repair_ttl); - assertEquals(DurationSpec.inMilliseconds(2000), config.permissions_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(250), config.cdc_free_space_check_interval); + assertEquals(new DurationSpec.IntMillisecondsBound(100), config.dynamic_snitch_update_interval); + assertEquals(new DurationSpec.IntMillisecondsBound(600000), config.dynamic_snitch_reset_interval); + assertEquals(new DurationSpec.IntMillisecondsBound(200), config.gc_log_threshold); + assertEquals(new DurationSpec.IntMillisecondsBound(10000), config.hints_flush_period); + assertEquals(new DurationSpec.IntMillisecondsBound(1000), config.gc_warn_threshold); + assertEquals(new DurationSpec.IntSecondsBound(86400), config.trace_type_query_ttl); + assertEquals(new DurationSpec.IntSecondsBound(604800), config.trace_type_repair_ttl); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.permissions_validity); assertNull(config.permissions_update_interval); - assertEquals(DurationSpec.inMilliseconds(2000), config.roles_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.roles_validity); assertNull(config.roles_update_interval); - assertEquals(DurationSpec.inMilliseconds(2000), config.credentials_validity); + assertEquals(new DurationSpec.IntMillisecondsBound(2000), config.credentials_validity); assertNull(config.credentials_update_interval); - assertEquals(DurationSpec.inMinutes(60), config.index_summary_resize_interval); - assertEquals(DurationSpec.inHours(4), config.key_cache_save_period); - assertEquals(DurationSpec.inSeconds(30), config.cache_load_timeout); - assertEquals(DurationSpec.inMilliseconds(1500), config.user_defined_functions_fail_timeout); - assertEquals(DurationSpec.inMilliseconds(500), config.user_defined_functions_warn_timeout); - assertEquals(DurationSpec.inSeconds(3600), config.validation_preview_purge_head_start); + assertEquals(new DurationSpec.IntMinutesBound(60), config.index_summary_resize_interval); + assertEquals(DurationSpec.IntSecondsBound.inSecondsString("4h"), config.key_cache_save_period); + assertEquals(new DurationSpec.IntSecondsBound(30), config.cache_load_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(1500), config.user_defined_functions_fail_timeout); + assertEquals(new DurationSpec.LongMillisecondsBound(500), config.user_defined_functions_warn_timeout); + assertEquals(new DurationSpec.IntSecondsBound(3600), config.validation_preview_purge_head_start); //Confirm space parameters were successfully parsed with the default values in cassandra.yaml assertNull(config.memtable_heap_space); assertNull(config.memtable_offheap_space); assertNull(config.repair_session_space); //null everywhere so should be correct, let's check whether it will bomb - assertEquals(DataStorageSpec.inBytes(4194304), config.internode_application_send_queue_capacity); - assertEquals(DataStorageSpec.inBytes(134217728), config.internode_application_send_queue_reserve_endpoint_capacity); - assertEquals(DataStorageSpec.inBytes(536870912), config.internode_application_send_queue_reserve_global_capacity); - assertEquals(DataStorageSpec.inBytes(4194304), config.internode_application_receive_queue_capacity); - assertEquals(DataStorageSpec.inBytes(134217728), config.internode_application_receive_queue_reserve_endpoint_capacity); - assertEquals(DataStorageSpec.inBytes(536870912), config.internode_application_receive_queue_reserve_global_capacity); - assertEquals(DataStorageSpec.inMebibytes(16), config.native_transport_max_frame_size); - assertEquals(DataStorageSpec.inMebibytes(256), config.max_value_size); - assertEquals(DataStorageSpec.inKibibytes(4), config.column_index_size); - assertEquals(DataStorageSpec.inKibibytes(2), config.column_index_cache_size); - assertEquals(DataStorageSpec.inKibibytes(5), config.batch_size_warn_threshold); - assertEquals(DataStorageSpec.inKibibytes(50), config.batch_size_fail_threshold); - assertEquals(DataStorageSpec.inMebibytes(100), config.compaction_large_partition_warning_threshold); + assertEquals(new DataStorageSpec.IntBytesBound(4194304), config.internode_application_send_queue_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(134217728), config.internode_application_send_queue_reserve_endpoint_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(536870912), config.internode_application_send_queue_reserve_global_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(4194304), config.internode_application_receive_queue_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(134217728), config.internode_application_receive_queue_reserve_endpoint_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(536870912), config.internode_application_receive_queue_reserve_global_capacity); + assertEquals(new DataStorageSpec.IntMebibytesBound(16), config.native_transport_max_frame_size); + assertEquals(new DataStorageSpec.IntMebibytesBound(256), config.max_value_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(4), config.column_index_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(2), config.column_index_cache_size); + assertEquals(new DataStorageSpec.IntKibibytesBound(5), config.batch_size_warn_threshold); + assertEquals(new DataStorageSpec.IntKibibytesBound(50), config.batch_size_fail_threshold); + assertEquals(new DataStorageSpec.IntMebibytesBound(100), config.compaction_large_partition_warning_threshold); assertNull(config.commitlog_total_space); - assertEquals(DataStorageSpec.inMebibytes(5), config.commitlog_segment_size); + assertEquals(new DataStorageSpec.IntMebibytesBound(5), config.commitlog_segment_size); assertNull(config.max_mutation_size); //not set explicitly in the default yaml, check the config; not set there too - assertEquals(DataStorageSpec.inMebibytes(0), config.cdc_total_space); - assertEquals(DataStorageSpec.inKibibytes(1024), config.hinted_handoff_throttle); - assertEquals(DataStorageSpec.inKibibytes(1024), config.batchlog_replay_throttle); - assertEquals(DataStorageSpec.inKibibytes(10240), config.trickle_fsync_interval); - assertEquals(DataStorageSpec.inMebibytes(50), config.sstable_preemptive_open_interval); + assertEquals(new DataStorageSpec.IntMebibytesBound(0), config.cdc_total_space); + assertEquals(new DataStorageSpec.IntKibibytesBound(1024), config.hinted_handoff_throttle); + assertEquals(new DataStorageSpec.IntKibibytesBound(1024), config.batchlog_replay_throttle); + assertEquals(new DataStorageSpec.IntKibibytesBound(10240), config.trickle_fsync_interval); + assertEquals(new DataStorageSpec.IntMebibytesBound(50), config.sstable_preemptive_open_interval); assertNull(config.counter_cache_size); assertNull(config.file_cache_size); assertNull(config.index_summary_capacity); - assertEquals(DataStorageSpec.inMebibytes(1), config.prepared_statements_cache_size); + assertEquals(new DataStorageSpec.LongMebibytesBound(1), config.prepared_statements_cache_size); assertNull(config.key_cache_size); - assertEquals(DataStorageSpec.inMebibytes(16), config.row_cache_size); + assertEquals(new DataStorageSpec.LongMebibytesBound(16), config.row_cache_size); assertNull(config.native_transport_max_request_data_in_flight); assertNull(config.native_transport_max_request_data_in_flight_per_ip); - assertEquals(DataStorageSpec.inMebibytes(1), config.native_transport_receive_queue_capacity); + assertEquals(new DataStorageSpec.IntBytesBound(1, MEBIBYTES), config.native_transport_receive_queue_capacity); //Confirm rate parameters were successfully parsed with the default values in cassandra.yaml - assertEquals(DataRateSpec.inMebibytesPerSecond(0), config.compaction_throughput); - assertEquals(DataRateSpec.inMebibytesPerSecond(23841858), config.stream_throughput_outbound); - assertEquals(DataRateSpec.inMebibytesPerSecond(24), config.inter_dc_stream_throughput_outbound); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(0), config.compaction_throughput); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(23841858), config.stream_throughput_outbound); + assertEquals(new DataRateSpec.IntMebibytesPerSecondBound(24), config.inter_dc_stream_throughput_outbound); } -} \ No newline at end of file +} diff --git a/test/unit/org/apache/cassandra/config/PropertiesTest.java b/test/unit/org/apache/cassandra/config/PropertiesTest.java index f1e9322f3b..6fec2dfe68 100644 --- a/test/unit/org/apache/cassandra/config/PropertiesTest.java +++ b/test/unit/org/apache/cassandra/config/PropertiesTest.java @@ -73,7 +73,7 @@ public class PropertiesTest ps.get("cluster_name").set(config, "properties testing"); assertThat(config.cluster_name).isEqualTo("properties testing"); - ps.get("permissions_validity").set(config, SmallestDurationMilliseconds.inMilliseconds(42)); + ps.get("permissions_validity").set(config, new DurationSpec.IntMillisecondsBound(42)); assertThat(config.permissions_validity.toMilliseconds()).isEqualTo(42); ps.get("hinted_handoff_disabled_datacenters").set(config, Sets.newHashSet("a", "b", "c")); diff --git a/test/unit/org/apache/cassandra/config/SmallestDataStorageKibibytesTest.java b/test/unit/org/apache/cassandra/config/SmallestDataStorageKibibytesTest.java deleted file mode 100644 index d60eb758e8..0000000000 --- a/test/unit/org/apache/cassandra/config/SmallestDataStorageKibibytesTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; - -public class SmallestDataStorageKibibytesTest -{ - @Test - public void testInvalidUnits() - { - assertThatThrownBy(() -> new SmallestDataStorageKibibytes("10B")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: 10B"); - } - - @Test - public void testValidUnits() - { - assertEquals(10L, new SmallestDataStorageKibibytes("10KiB").toKibibytes()); - } -} diff --git a/test/unit/org/apache/cassandra/config/SmallestDataStorageMebibytesTest.java b/test/unit/org/apache/cassandra/config/SmallestDataStorageMebibytesTest.java deleted file mode 100644 index 996ce45fd9..0000000000 --- a/test/unit/org/apache/cassandra/config/SmallestDataStorageMebibytesTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; - -public class SmallestDataStorageMebibytesTest -{ - @Test - public void testInvalidUnits() - { - assertThatThrownBy(() -> new SmallestDataStorageMebibytes("10B")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid data storage: 10B"); - } - - @Test - public void testValidUnits() - { - assertEquals(10L, new SmallestDataStorageMebibytes("10MiB").toMebibytes()); - } -} diff --git a/test/unit/org/apache/cassandra/config/SmallestDurationMillisecondsTest.java b/test/unit/org/apache/cassandra/config/SmallestDurationMillisecondsTest.java deleted file mode 100644 index 890d69adef..0000000000 --- a/test/unit/org/apache/cassandra/config/SmallestDurationMillisecondsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; - -public class SmallestDurationMillisecondsTest -{ - @Test - public void testInvalidUnits() - { - assertThatThrownBy(() -> new SmallestDurationMilliseconds("10ns")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10ns"); - assertThatThrownBy(() -> new SmallestDurationMilliseconds("10us")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10us"); - assertThatThrownBy(() -> new SmallestDurationMilliseconds("10µs")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10µs"); - assertThatThrownBy(() -> new SmallestDurationMilliseconds("-10s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: -10s"); - } - - @Test - public void testValidUnits() - { - assertEquals(10L, new SmallestDurationMilliseconds("10ms").toMilliseconds()); - } -} diff --git a/test/unit/org/apache/cassandra/config/SmallestDurationMinutesTest.java b/test/unit/org/apache/cassandra/config/SmallestDurationMinutesTest.java deleted file mode 100644 index a850d15769..0000000000 --- a/test/unit/org/apache/cassandra/config/SmallestDurationMinutesTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; - -public class SmallestDurationMinutesTest -{ - @Test - public void testInvalidUnits() - { - assertThatThrownBy(() -> new SmallestDurationMinutes("10s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10s"); - assertThatThrownBy(() -> new SmallestDurationMinutes("10ms")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10ms"); - assertThatThrownBy(() -> new SmallestDurationMinutes("10ns")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10ns"); - assertThatThrownBy(() -> new SmallestDurationMinutes("10us")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10us"); - assertThatThrownBy(() -> new SmallestDurationMinutes("10µs")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10µs"); - assertThatThrownBy(() -> new SmallestDurationMinutes("-10s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: -10s"); - } - - @Test - public void testValidUnits() - { - assertEquals(10L, new SmallestDurationMinutes("10m").toMinutes()); - } -} diff --git a/test/unit/org/apache/cassandra/config/SmallestDurationSecondsTest.java b/test/unit/org/apache/cassandra/config/SmallestDurationSecondsTest.java deleted file mode 100644 index 8380a852f8..0000000000 --- a/test/unit/org/apache/cassandra/config/SmallestDurationSecondsTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; - -public class SmallestDurationSecondsTest -{ - @Test - public void testInvalidUnits() - { - assertThatThrownBy(() -> new SmallestDurationSeconds("10ms")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10ms"); - assertThatThrownBy(() -> new SmallestDurationSeconds("10ns")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10ns"); - assertThatThrownBy(() -> new SmallestDurationSeconds("10us")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10us"); - assertThatThrownBy(() -> new SmallestDurationSeconds("10µs")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: 10µs"); - assertThatThrownBy(() -> new SmallestDurationSeconds("-10s")).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Invalid duration: -10s"); - } - - @Test - public void testValidUnits() - { - assertEquals(10L, new SmallestDurationSeconds("10s").toSeconds()); - } -} diff --git a/test/unit/org/apache/cassandra/config/YamlConfigurationLoaderTest.java b/test/unit/org/apache/cassandra/config/YamlConfigurationLoaderTest.java index fd7bc4050f..8c4949f0e4 100644 --- a/test/unit/org/apache/cassandra/config/YamlConfigurationLoaderTest.java +++ b/test/unit/org/apache/cassandra/config/YamlConfigurationLoaderTest.java @@ -18,11 +18,14 @@ package org.apache.cassandra.config; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Collections; import java.util.Map; +import java.util.function.Predicate; import com.google.common.collect.ImmutableMap; import org.junit.Test; @@ -32,6 +35,7 @@ import org.apache.cassandra.io.util.File; import org.yaml.snakeyaml.error.YAMLException; import static org.apache.cassandra.config.CassandraRelevantProperties.CONFIG_ALLOW_SYSTEM_PROPERTIES; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.KIBIBYTES; import static org.apache.cassandra.config.YamlConfigurationLoader.SYSTEM_PROPERTY_PREFIX; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -41,6 +45,20 @@ import static org.junit.Assert.assertTrue; public class YamlConfigurationLoaderTest { + @Test + public void validateTypes() + { + Predicate isDurationSpec = f -> f.getType().getTypeName().equals("org.apache.cassandra.config.DurationSpec"); + Predicate isDataStorageSpec = f -> f.getType().getTypeName().equals("org.apache.cassandra.config.DataStorageSpec"); + Predicate isDataRateSpec = f -> f.getType().getTypeName().equals("org.apache.cassandra.config.DataRateSpec"); + + assertEquals("You have wrongly defined a config parameter of abstract type DurationSpec, DataStorageSpec or DataRateSpec." + + "Please check the config docs, otherwise Cassandra won't be able to start with this parameter being set in cassandra.yaml.", + Arrays.stream(Config.class.getFields()) + .filter(f -> !Modifier.isStatic(f.getModifiers())) + .filter(isDurationSpec.or(isDataRateSpec).or(isDataStorageSpec)).count(), 0); + } + @Test public void updateInPlace() { @@ -99,14 +117,14 @@ public class YamlConfigurationLoaderTest assertThat(c.read_thresholds_enabled).isTrue(); - assertThat(c.coordinator_read_size_warn_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 10)); - assertThat(c.coordinator_read_size_fail_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 12)); + assertThat(c.coordinator_read_size_warn_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 10, KIBIBYTES)); + assertThat(c.coordinator_read_size_fail_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 12, KIBIBYTES)); - assertThat(c.local_read_size_warn_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 12)); - assertThat(c.local_read_size_fail_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 13)); + assertThat(c.local_read_size_warn_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 12, KIBIBYTES)); + assertThat(c.local_read_size_fail_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 13, KIBIBYTES)); - assertThat(c.row_index_read_size_warn_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 12)); - assertThat(c.row_index_read_size_fail_threshold).isEqualTo(DataStorageSpec.inKibibytes(1 << 13)); + assertThat(c.row_index_read_size_warn_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 12, KIBIBYTES)); + assertThat(c.row_index_read_size_fail_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1 << 13, KIBIBYTES)); } @Test @@ -124,14 +142,14 @@ public class YamlConfigurationLoaderTest Config c = YamlConfigurationLoader.fromMap(map, Config.class); assertThat(c.read_thresholds_enabled).isTrue(); - assertThat(c.coordinator_read_size_warn_threshold).isEqualTo(DataStorageSpec.inKibibytes(1024)); + assertThat(c.coordinator_read_size_warn_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1024, KIBIBYTES)); assertThat(c.coordinator_read_size_fail_threshold).isNull(); assertThat(c.local_read_size_warn_threshold).isNull(); - assertThat(c.local_read_size_fail_threshold).isEqualTo(DataStorageSpec.inKibibytes(1024)); + assertThat(c.local_read_size_fail_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1024, KIBIBYTES)); - assertThat(c.row_index_read_size_warn_threshold).isEqualTo(DataStorageSpec.inKibibytes(1024)); - assertThat(c.row_index_read_size_fail_threshold).isEqualTo(DataStorageSpec.inKibibytes(1024)); + assertThat(c.row_index_read_size_warn_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1024, KIBIBYTES)); + assertThat(c.row_index_read_size_fail_threshold).isEqualTo(new DataStorageSpec.LongBytesBound(1024, KIBIBYTES)); } @Test @@ -181,8 +199,8 @@ public class YamlConfigurationLoaderTest assertEquals(seedProvider, config.seed_provider); // Check a parameterized class assertEquals(false, config.client_encryption_options.optional); // Check a nested object assertEquals(true, config.client_encryption_options.enabled); // Check a nested object - assertEquals(new DataStorageSpec("5B"), config.internode_socket_send_buffer_size); // Check names backward compatibility (CASSANDRA-17141 and CASSANDRA-15234) - assertEquals(new DataStorageSpec("5B"), config.internode_socket_receive_buffer_size); // Check names backward compatibility (CASSANDRA-17141 and CASSANDRA-15234) + assertEquals(new DataStorageSpec.IntBytesBound("5B"), config.internode_socket_send_buffer_size); // Check names backward compatibility (CASSANDRA-17141 and CASSANDRA-15234) + assertEquals(new DataStorageSpec.IntBytesBound("5B"), config.internode_socket_receive_buffer_size); // Check names backward compatibility (CASSANDRA-17141 and CASSANDRA-15234) } @Test @@ -194,9 +212,9 @@ public class YamlConfigurationLoaderTest Config latest = YamlConfigurationLoader.fromMap(ImmutableMap.of("key_cache_save_period", "42s", "row_cache_save_period", "42s", "counter_cache_save_period", "42s"), Config.class); - assertThat(old.key_cache_save_period).isEqualTo(latest.key_cache_save_period).isEqualTo(SmallestDurationSeconds.inSeconds(42)); - assertThat(old.row_cache_save_period).isEqualTo(latest.row_cache_save_period).isEqualTo(SmallestDurationSeconds.inSeconds(42)); - assertThat(old.counter_cache_save_period).isEqualTo(latest.counter_cache_save_period).isEqualTo(SmallestDurationSeconds.inSeconds(42)); + assertThat(old.key_cache_save_period).isEqualTo(latest.key_cache_save_period).isEqualTo(new DurationSpec.IntSecondsBound(42)); + assertThat(old.row_cache_save_period).isEqualTo(latest.row_cache_save_period).isEqualTo(new DurationSpec.IntSecondsBound(42)); + assertThat(old.counter_cache_save_period).isEqualTo(latest.counter_cache_save_period).isEqualTo(new DurationSpec.IntSecondsBound(42)); } @Test @@ -224,20 +242,20 @@ public class YamlConfigurationLoaderTest assertThat(from("commitlog_sync_group_window_in_ms", "NaN").commitlog_sync_group_window.toMilliseconds()).isEqualTo(0); assertThatThrownBy(() -> from("commitlog_sync_group_window_in_ms", -2).commitlog_sync_group_window.toMilliseconds()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid duration -2: value must be positive"); + .hasRootCauseMessage("Invalid duration: value must be non-negative"); // MILLIS_CUSTOM_DURATION - assertThat(from("permissions_update_interval_in_ms", 42).permissions_update_interval).isEqualTo(SmallestDurationMilliseconds.inMilliseconds(42)); + assertThat(from("permissions_update_interval_in_ms", 42).permissions_update_interval).isEqualTo(new DurationSpec.IntMillisecondsBound(42)); assertThat(from("permissions_update_interval_in_ms", -1).permissions_update_interval).isNull(); assertThatThrownBy(() -> from("permissions_update_interval_in_ms", -2)) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid duration -2: value must be positive"); + .hasRootCauseMessage("Invalid duration: value must be non-negative"); // SECONDS_DURATION assertThat(from("streaming_keep_alive_period_in_secs", "42").streaming_keep_alive_period.toSeconds()).isEqualTo(42); assertThatThrownBy(() -> from("streaming_keep_alive_period_in_secs", -2).streaming_keep_alive_period.toSeconds()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid duration -2: value must be positive"); + .hasRootCauseMessage("Invalid duration: value must be non-negative"); // NEGATIVE_SECONDS_DURATION assertThat(from("validation_preview_purge_head_start_in_sec", -1).validation_preview_purge_head_start.toSeconds()).isEqualTo(0); @@ -250,7 +268,7 @@ public class YamlConfigurationLoaderTest assertThat(from("index_summary_resize_interval_in_minutes", "42").index_summary_resize_interval.toMinutes()).isEqualTo(42); assertThatThrownBy(() -> from("index_summary_resize_interval_in_minutes", -2).index_summary_resize_interval.toMinutes()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid duration -2: value must be positive"); + .hasRootCauseMessage("Invalid duration: value must be non-negative"); // BYTES_CUSTOM_DATASTORAGE assertThat(from("native_transport_max_concurrent_requests_in_bytes_per_ip", -1).native_transport_max_request_data_in_flight_per_ip).isEqualTo(null); @@ -261,37 +279,37 @@ public class YamlConfigurationLoaderTest assertThat(from("memtable_heap_space_in_mb", "42").memtable_heap_space.toMebibytes()).isEqualTo(42); assertThatThrownBy(() -> from("memtable_heap_space_in_mb", -2).memtable_heap_space.toMebibytes()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid data storage: value must be positive, but was -2"); + .hasRootCauseMessage("Invalid data storage: value must be non-negative"); // KIBIBYTES_DATASTORAGE assertThat(from("column_index_size_in_kb", "42").column_index_size.toKibibytes()).isEqualTo(42); - assertThatThrownBy(() -> from("column_index_size_in_kb", -2).column_index_size.toMebibytes()) + assertThatThrownBy(() -> from("column_index_size_in_kb", -2).column_index_size.toKibibytes()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid data storage: value must be positive, but was -2"); + .hasRootCauseMessage("Invalid data storage: value must be non-negative"); // BYTES_DATASTORAGE assertThat(from("internode_max_message_size_in_bytes", "42").internode_max_message_size.toBytes()).isEqualTo(42); assertThatThrownBy(() -> from("internode_max_message_size_in_bytes", -2).internode_max_message_size.toBytes()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid data storage: value must be positive, but was -2"); + .hasRootCauseMessage("Invalid data storage: value must be non-negative"); // BYTES_DATASTORAGE assertThat(from("internode_max_message_size_in_bytes", "42").internode_max_message_size.toBytes()).isEqualTo(42); assertThatThrownBy(() -> from("internode_max_message_size_in_bytes", -2).internode_max_message_size.toBytes()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid data storage: value must be positive, but was -2"); + .hasRootCauseMessage("Invalid data storage: value must be non-negative"); // MEBIBYTES_PER_SECOND_DATA_RATE assertThat(from("compaction_throughput_mb_per_sec", "42").compaction_throughput.toMebibytesPerSecondAsInt()).isEqualTo(42); assertThatThrownBy(() -> from("compaction_throughput_mb_per_sec", -2).compaction_throughput.toMebibytesPerSecondAsInt()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid bit rate: value must be non-negative"); + .hasRootCauseMessage("Invalid data rate: value must be non-negative"); // MEGABITS_TO_MEBIBYTES_PER_SECOND_DATA_RATE assertThat(from("stream_throughput_outbound_megabits_per_sec", "42").stream_throughput_outbound.toMegabitsPerSecondAsInt()).isEqualTo(42); assertThatThrownBy(() -> from("stream_throughput_outbound_megabits_per_sec", -2).stream_throughput_outbound.toMegabitsPerSecondAsInt()) .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasRootCauseMessage("Invalid bit rate: value must be non-negative"); + .hasRootCauseMessage("Invalid data rate: value must be non-negative"); } private static Config from(Object... values) diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java index f5e93e8985..eae939b8a9 100644 --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@ -68,8 +68,8 @@ import org.apache.cassandra.auth.AuthTestUtils; import org.apache.cassandra.auth.IRoleManager; import org.apache.cassandra.concurrent.ScheduledExecutors; import org.apache.cassandra.concurrent.Stage; +import org.apache.cassandra.config.DataStorageSpec; import org.apache.cassandra.config.EncryptionOptions; -import org.apache.cassandra.config.SmallestDataStorageMebibytes; import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry; import org.apache.cassandra.db.virtual.VirtualSchemaKeyspace; import org.apache.cassandra.exceptions.InvalidRequestException; @@ -131,7 +131,7 @@ public abstract class CQLTester public static final String KEYSPACE_PER_TEST = "cql_test_keyspace_alt"; protected static final boolean USE_PREPARED_VALUES = Boolean.valueOf(System.getProperty("cassandra.test.use_prepared", "true")); protected static final boolean REUSE_PREPARED = Boolean.valueOf(System.getProperty("cassandra.test.reuse_prepared", "true")); - protected static final long ROW_CACHE_SIZE_IN_MIB = new SmallestDataStorageMebibytes(System.getProperty("cassandra.test.row_cache_size", "0MiB")).toMebibytes(); + protected static final long ROW_CACHE_SIZE_IN_MIB = new DataStorageSpec.LongMebibytesBound(System.getProperty("cassandra.test.row_cache_size", "0MiB")).toMebibytes(); private static final AtomicInteger seqNumber = new AtomicInteger(); protected static final ByteBuffer TOO_BIG = ByteBuffer.allocate(FBUtilities.MAX_UNSIGNED_SHORT + 1024); public static final String DATA_CENTER = ServerTestUtils.DATA_CENTER; diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/AutoSnapshotTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/AutoSnapshotTest.java index 839ca44b28..ecb84f3285 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/AutoSnapshotTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AutoSnapshotTest.java @@ -38,6 +38,7 @@ import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.service.snapshot.TableSnapshot; import org.assertj.core.api.Condition; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.cassandra.db.ColumnFamilyStore.SNAPSHOT_DROP_PREFIX; import static org.assertj.core.api.Assertions.assertThat; @@ -47,7 +48,7 @@ public class AutoSnapshotTest extends CQLTester static int TTL_SECS = 1; public static Boolean enabledBefore; - public static DurationSpec ttlBefore; + public static DurationSpec.IntSecondsBound ttlBefore; @BeforeClass public static void beforeClass() @@ -68,7 +69,7 @@ public class AutoSnapshotTest extends CQLTester public Boolean autoSnapshotEnabled; @Parameterized.Parameter(1) - public DurationSpec autoSnapshotTTl; + public DurationSpec.IntSecondsBound autoSnapshotTTl; @Before public void beforeTest() throws Throwable @@ -83,8 +84,8 @@ public class AutoSnapshotTest extends CQLTester @Parameterized.Parameters( name = "enabled={0},ttl={1}" ) public static Collection options() { return Arrays.asList(new Object[][] { - { true, DurationSpec.inSeconds(TTL_SECS) }, - { false, DurationSpec.inSeconds(TTL_SECS) }, + { true, new DurationSpec.IntSecondsBound(TTL_SECS, SECONDS) }, + { false, new DurationSpec.IntSecondsBound(TTL_SECS, SECONDS) }, { true, null }, { false, null }, }); @@ -149,7 +150,7 @@ public class AutoSnapshotTest extends CQLTester { // check that snapshot has TTL and is expired after 1 second assertThat(snapshot.isExpiring()).isTrue(); - Uninterruptibles.sleepUninterruptibly(TTL_SECS, TimeUnit.SECONDS); + Uninterruptibles.sleepUninterruptibly(TTL_SECS, SECONDS); assertThat(snapshot.isExpired(Instant.now())).isTrue(); } } diff --git a/test/unit/org/apache/cassandra/db/DirectoriesTest.java b/test/unit/org/apache/cassandra/db/DirectoriesTest.java index 3779eccbec..252c630614 100644 --- a/test/unit/org/apache/cassandra/db/DirectoriesTest.java +++ b/test/unit/org/apache/cassandra/db/DirectoriesTest.java @@ -225,7 +225,7 @@ public class DirectoriesTest if (createManifest) { File manifestFile = Directories.getSnapshotManifestFile(snapshotDir); - manifest = new SnapshotManifest(Collections.singletonList(sstableDesc.filenameFor(Component.DATA)), new DurationSpec("1m"), now()); + manifest = new SnapshotManifest(Collections.singletonList(sstableDesc.filenameFor(Component.DATA)), new DurationSpec.IntSecondsBound("1m"), now()); manifest.serializeToJsonFile(manifestFile); } @@ -353,7 +353,7 @@ public class DirectoriesTest File manifestFile = directories.getSnapshotManifestFile(tag); - SnapshotManifest manifest = new SnapshotManifest(files, new DurationSpec("1m"), now()); + SnapshotManifest manifest = new SnapshotManifest(files, new DurationSpec.IntSecondsBound("1m"), now()); manifest.serializeToJsonFile(manifestFile); Set dirs = new HashSet<>(); diff --git a/test/unit/org/apache/cassandra/db/TopPartitionTrackerTest.java b/test/unit/org/apache/cassandra/db/TopPartitionTrackerTest.java index 938be11818..82ef177705 100644 --- a/test/unit/org/apache/cassandra/db/TopPartitionTrackerTest.java +++ b/test/unit/org/apache/cassandra/db/TopPartitionTrackerTest.java @@ -54,7 +54,7 @@ public class TopPartitionTrackerTest extends CQLTester { createTable("create table %s (id bigint primary key, x int)"); DatabaseDescriptor.setMaxTopSizePartitionCount(5); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("12B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("12B")); Collection> fullRange = Collections.singleton(r(0, 0)); TopPartitionTracker tpt = new TopPartitionTracker(getCurrentColumnFamilyStore().metadata()); @@ -85,7 +85,7 @@ public class TopPartitionTrackerTest extends CQLTester public void testCountLimit() { createTable("create table %s (id bigint primary key, x int)"); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("0B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("0B")); DatabaseDescriptor.setMaxTopSizePartitionCount(5); Collection> fullRange = Collections.singleton(r(0, 0)); TopPartitionTracker tpt = new TopPartitionTracker(getCurrentColumnFamilyStore().metadata()); @@ -111,7 +111,7 @@ public class TopPartitionTrackerTest extends CQLTester public void testSubRangeMerge() { createTable("create table %s (id bigint primary key, x int)"); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("0B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("0B")); DatabaseDescriptor.setMaxTopSizePartitionCount(10); Collection> fullRange = Collections.singleton(r(0, 0)); TopPartitionTracker tpt = new TopPartitionTracker(getCurrentColumnFamilyStore().metadata()); @@ -140,7 +140,7 @@ public class TopPartitionTrackerTest extends CQLTester public void testSaveLoad() { createTable("create table %s (id bigint primary key, x int)"); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("0B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("0B")); DatabaseDescriptor.setMinTrackedPartitionTombstoneCount(0); DatabaseDescriptor.setMaxTopSizePartitionCount(10); DatabaseDescriptor.setMaxTopTombstonePartitionCount(10); @@ -205,7 +205,7 @@ public class TopPartitionTrackerTest extends CQLTester public void randomTest() { createTable("create table %s (id bigint primary key, x int)"); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("0B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("0B")); DatabaseDescriptor.setMaxTopSizePartitionCount(1000); int keyCount = 10000; long seed = System.currentTimeMillis(); @@ -254,7 +254,7 @@ public class TopPartitionTrackerTest extends CQLTester public void testRanges() throws UnknownHostException { createTable("create table %s (id bigint primary key, x int)"); - DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec("0B")); + DatabaseDescriptor.setMinTrackedPartitionSize(new DataStorageSpec.LongBytesBound("0B")); DatabaseDescriptor.setMaxTopSizePartitionCount(1000); long seed = System.currentTimeMillis(); Random r = new Random(seed); diff --git a/test/unit/org/apache/cassandra/db/guardrails/GuardrailDiskUsageTest.java b/test/unit/org/apache/cassandra/db/guardrails/GuardrailDiskUsageTest.java index 10bf05bb8a..86e4df07b8 100644 --- a/test/unit/org/apache/cassandra/db/guardrails/GuardrailDiskUsageTest.java +++ b/test/unit/org/apache/cassandra/db/guardrails/GuardrailDiskUsageTest.java @@ -122,7 +122,8 @@ public class GuardrailDiskUsageTest extends GuardrailTester String message = String.format("only %s are actually available on disk", FileUtils.stringifyFileSize(diskSize)); assertConfigValid(x -> x.setDataDiskUsageMaxDiskSize(diskSize + "B")); assertConfigFails(x -> x.setDataDiskUsageMaxDiskSize(diskSize + 1 + "B"), message); - assertConfigFails(x -> x.setDataDiskUsageMaxDiskSize(Long.MAX_VALUE + "GiB"), message); + // We want to test with very big number, Long.MAX_VALUE is not allowed so it was easy to use Intger.MAX_VALUE + assertConfigFails(x -> x.setDataDiskUsageMaxDiskSize(Integer.MAX_VALUE + "GiB"), message); // warn threshold smaller than lower bound assertConfigFails(x -> x.setDataDiskUsagePercentageThreshold(0, 80), "0 is not allowed"); @@ -319,10 +320,10 @@ public class GuardrailDiskUsageTest extends GuardrailTester public void testDiskUsageCalculationWithMaxDiskSize() throws IOException { Directories.DataDirectory directory = mock(Directories.DataDirectory.class); - when(directory.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(5).toBytes()); + when(directory.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("5GiB").toBytes()); FileStore store = mock(FileStore.class); - when(store.getUsableSpace()).thenReturn(DataStorageSpec.inGibibytes(100 - 5).toBytes()); // 100GiB disk + when(store.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound("95GiB").toBytes()); // 100GiB disk - 5GiB Multimap directories = HashMultimap.create(); directories.put(store, directory); @@ -351,13 +352,13 @@ public class GuardrailDiskUsageTest extends GuardrailTester public void testDiskUsageCalculationWithMaxDiskSizeAndSmallUnits() throws IOException { // 5GiB used out of 100GiB disk - long freeDiskSizeInBytes = DataStorageSpec.inGibibytes(100).toBytes() - DataStorageSpec.inMebibytes(5).toBytes(); + long freeDiskSizeInBytes = new DataStorageSpec.LongBytesBound("100GiB").toBytes() - new DataStorageSpec.LongBytesBound("5MiB").toBytes(); FileStore store = mock(FileStore.class); - when(store.getUsableSpace()).thenReturn(DataStorageSpec.inBytes(freeDiskSizeInBytes).toBytes()); // 100GiB disk + when(store.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound(freeDiskSizeInBytes + "B").toBytes()); // 100GiB disk Directories.DataDirectory directory = mock(Directories.DataDirectory.class); - when(directory.getRawSize()).thenReturn(DataStorageSpec.inMebibytes(5).toBytes()); + when(directory.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("5MiB").toBytes()); Multimap directories = HashMultimap.create(); directories.put(store, directory); @@ -391,20 +392,20 @@ public class GuardrailDiskUsageTest extends GuardrailTester Directories.DataDirectory directory1 = mock(Directories.DataDirectory.class); FileStore store1 = mock(FileStore.class); - when(directory1.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(5).toBytes()); - when(store1.getUsableSpace()).thenReturn(DataStorageSpec.inGibibytes(100 - 5).toBytes()); // 100 GiB disk + when(directory1.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("5GiB").toBytes()); + when(store1.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound("95GiB").toBytes()); // 100 GiB disk - 5 GiB directories.put(store1, directory1); Directories.DataDirectory directory2 = mock(Directories.DataDirectory.class); FileStore store2 = mock(FileStore.class); - when(directory2.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(25).toBytes()); - when(store2.getUsableSpace()).thenReturn(DataStorageSpec.inGibibytes(100 - 25).toBytes()); // 100 GiB disk + when(directory2.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("25GiB").toBytes()); + when(store2.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound("75GiB").toBytes()); // 100 GiB disk - 25 GiB directories.put(store2, directory2); Directories.DataDirectory directory3 = mock(Directories.DataDirectory.class); FileStore store3 = mock(FileStore.class); - when(directory3.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(20).toBytes()); - when(store3.getUsableSpace()).thenReturn(DataStorageSpec.inGibibytes(100 - 20).toBytes()); // 100 GiB disk + when(directory3.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("20GiB").toBytes()); + when(store3.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound("80GiB").toBytes()); // 100 GiB disk - 20 GiB directories.put(store3, directory3); DiskUsageMonitor monitor = spy(new DiskUsageMonitor(() -> directories)); @@ -439,16 +440,16 @@ public class GuardrailDiskUsageTest extends GuardrailTester Mockito.reset(); Directories.DataDirectory directory1 = mock(Directories.DataDirectory.class); - when(directory1.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(5).toBytes()); + when(directory1.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("5GiB").toBytes()); Directories.DataDirectory directory2 = mock(Directories.DataDirectory.class); - when(directory2.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(25).toBytes()); + when(directory2.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("25GiB").toBytes()); Directories.DataDirectory directory3 = mock(Directories.DataDirectory.class); - when(directory3.getRawSize()).thenReturn(DataStorageSpec.inGibibytes(20).toBytes()); + when(directory3.getRawSize()).thenReturn(new DataStorageSpec.LongBytesBound("20GiB").toBytes()); FileStore store = mock(FileStore.class); - when(store.getUsableSpace()).thenReturn(DataStorageSpec.inGibibytes(300 - 5 - 25 - 20).toBytes()); // 100 GiB disk + when(store.getUsableSpace()).thenReturn(new DataStorageSpec.LongBytesBound("250GiB").toBytes()); // 100 GiB disk (300 - 5 - 25 - 20) Multimap directories = HashMultimap.create(); directories.putAll(store, ImmutableSet.of(directory1, directory2, directory3)); diff --git a/test/unit/org/apache/cassandra/db/guardrails/ThresholdTester.java b/test/unit/org/apache/cassandra/db/guardrails/ThresholdTester.java index ebd3c0304c..fae305ab7d 100644 --- a/test/unit/org/apache/cassandra/db/guardrails/ThresholdTester.java +++ b/test/unit/org/apache/cassandra/db/guardrails/ThresholdTester.java @@ -32,6 +32,7 @@ import org.apache.cassandra.config.DataStorageSpec; import org.assertj.core.api.Assertions; import static java.lang.String.format; +import static org.apache.cassandra.config.DataStorageSpec.DataStorageUnit.BYTES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; @@ -91,12 +92,12 @@ public abstract class ThresholdTester extends GuardrailTester Function failGetter) { super(threshold); - this.warnThreshold = new DataStorageSpec(warnThreshold).toBytes(); - this.failThreshold = new DataStorageSpec(failThreshold).toBytes(); - this.setter = (g, w, a) -> setter.accept(g, w == null ? null : DataStorageSpec.inBytes(w).toString(), a == null ? null : DataStorageSpec.inBytes(a).toString()); - this.warnGetter = g -> new DataStorageSpec(warnGetter.apply(g)).toBytes(); - this.failGetter = g -> new DataStorageSpec(failGetter.apply(g)).toBytes(); - maxValue = Long.MAX_VALUE; + this.warnThreshold = new DataStorageSpec.LongBytesBound(warnThreshold).toBytes(); + this.failThreshold = new DataStorageSpec.LongBytesBound(failThreshold).toBytes(); + this.setter = (g, w, a) -> setter.accept(g, w == null ? null : new DataStorageSpec.LongBytesBound(w, BYTES).toString(), a == null ? null : new DataStorageSpec.LongBytesBound(a, BYTES).toString()); + this.warnGetter = g -> new DataStorageSpec.LongBytesBound(warnGetter.apply(g)).toBytes(); + this.failGetter = g -> new DataStorageSpec.LongBytesBound(failGetter.apply(g)).toBytes(); + maxValue = Long.MAX_VALUE - 1; disabledValue = null; } @@ -246,7 +247,7 @@ public abstract class ThresholdTester extends GuardrailTester value, name, disabledValue); if (expectedMessage == null && value < 0) - expectedMessage = format("Invalid data storage: value must be positive, but was %d", value); + expectedMessage = format("Invalid data storage: value must be non-negative"); assertEquals(format("Exception message '%s' does not contain '%s'", e.getMessage(), expectedMessage), expectedMessage, e.getMessage()); diff --git a/test/unit/org/apache/cassandra/db/virtual/CredentialsCacheKeysTableTest.java b/test/unit/org/apache/cassandra/db/virtual/CredentialsCacheKeysTableTest.java index cdb14abb19..45132a962e 100644 --- a/test/unit/org/apache/cassandra/db/virtual/CredentialsCacheKeysTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/CredentialsCacheKeysTableTest.java @@ -74,7 +74,7 @@ public class CredentialsCacheKeysTableTest extends CQLTester @AfterClass public static void tearDownClass() { - DatabaseDescriptor.setCredentialsValidity(DatabaseDescriptor.getRawConfig().credentials_validity.toMillisecondsAsInt()); + DatabaseDescriptor.setCredentialsValidity(DatabaseDescriptor.getRawConfig().credentials_validity.toMilliseconds()); } @Test diff --git a/test/unit/org/apache/cassandra/db/virtual/JmxPermissionsCacheKeysTableTest.java b/test/unit/org/apache/cassandra/db/virtual/JmxPermissionsCacheKeysTableTest.java index 363dfd7878..1dfe622d49 100644 --- a/test/unit/org/apache/cassandra/db/virtual/JmxPermissionsCacheKeysTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/JmxPermissionsCacheKeysTableTest.java @@ -95,7 +95,7 @@ public class JmxPermissionsCacheKeysTableTest extends CQLTester @AfterClass public static void tearDownClass() { - DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMillisecondsAsInt()); + DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMilliseconds()); } @Test diff --git a/test/unit/org/apache/cassandra/db/virtual/NetworkPermissionsCacheKeysTableTest.java b/test/unit/org/apache/cassandra/db/virtual/NetworkPermissionsCacheKeysTableTest.java index e329d8810c..f944884098 100644 --- a/test/unit/org/apache/cassandra/db/virtual/NetworkPermissionsCacheKeysTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/NetworkPermissionsCacheKeysTableTest.java @@ -75,7 +75,7 @@ public class NetworkPermissionsCacheKeysTableTest extends CQLTester @AfterClass public static void tearDownClass() { - DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMillisecondsAsInt()); + DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMilliseconds()); } @Test diff --git a/test/unit/org/apache/cassandra/db/virtual/PermissionsCacheKeysTableTest.java b/test/unit/org/apache/cassandra/db/virtual/PermissionsCacheKeysTableTest.java index 97406e401d..2171b2d035 100644 --- a/test/unit/org/apache/cassandra/db/virtual/PermissionsCacheKeysTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/PermissionsCacheKeysTableTest.java @@ -90,7 +90,7 @@ public class PermissionsCacheKeysTableTest extends CQLTester @AfterClass public static void tearDownClass() { - DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMillisecondsAsInt()); + DatabaseDescriptor.setPermissionsValidity(DatabaseDescriptor.getRawConfig().permissions_validity.toMilliseconds()); } @Test diff --git a/test/unit/org/apache/cassandra/db/virtual/RolesCacheKeysTableTest.java b/test/unit/org/apache/cassandra/db/virtual/RolesCacheKeysTableTest.java index ce8beeaf60..40c3037005 100644 --- a/test/unit/org/apache/cassandra/db/virtual/RolesCacheKeysTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/RolesCacheKeysTableTest.java @@ -75,7 +75,7 @@ public class RolesCacheKeysTableTest extends CQLTester @AfterClass public static void tearDownClass() { - DatabaseDescriptor.setRolesValidity(DatabaseDescriptor.getRawConfig().roles_validity.toMillisecondsAsInt()); + DatabaseDescriptor.setRolesValidity(DatabaseDescriptor.getRawConfig().roles_validity.toMilliseconds()); } @Test diff --git a/test/unit/org/apache/cassandra/service/snapshot/SnapshotLoaderTest.java b/test/unit/org/apache/cassandra/service/snapshot/SnapshotLoaderTest.java index 27f294e8d5..21ab7d9b11 100644 --- a/test/unit/org/apache/cassandra/service/snapshot/SnapshotLoaderTest.java +++ b/test/unit/org/apache/cassandra/service/snapshot/SnapshotLoaderTest.java @@ -154,7 +154,7 @@ public class SnapshotLoaderTest // Write manifest for snapshot tag2 on random location Instant tag2Ts = Instant.now().plusSeconds(10); - DurationSpec tag2Ttl = new DurationSpec("10h"); + DurationSpec.IntSecondsBound tag2Ttl = new DurationSpec.IntSecondsBound("10h"); File tag2ManifestLocation = tag2Files.toArray(new File[0])[ThreadLocalRandom.current().nextInt(tag2Files.size())]; writeManifest(tag2ManifestLocation, tag2Ts, tag2Ttl); @@ -206,7 +206,7 @@ public class SnapshotLoaderTest assertThat(SnapshotLoader.parseUUID("c7e513243f0711ec9bbc0242ac130002")).isEqualTo(UUID.fromString("c7e51324-3f07-11ec-9bbc-0242ac130002")); } - private void writeManifest(File snapshotDir, Instant creationTime, DurationSpec ttl) throws IOException + private void writeManifest(File snapshotDir, Instant creationTime, DurationSpec.IntSecondsBound ttl) throws IOException { SnapshotManifest manifest = new SnapshotManifest(Lists.newArrayList("f1", "f2", "f3"), ttl, creationTime); manifest.serializeToJsonFile(getManifestFile(snapshotDir)); diff --git a/test/unit/org/apache/cassandra/service/snapshot/SnapshotManifestTest.java b/test/unit/org/apache/cassandra/service/snapshot/SnapshotManifestTest.java index 4239d50027..d3b11c0643 100644 --- a/test/unit/org/apache/cassandra/service/snapshot/SnapshotManifestTest.java +++ b/test/unit/org/apache/cassandra/service/snapshot/SnapshotManifestTest.java @@ -108,7 +108,7 @@ public class SnapshotManifestTest @Test public void testSerializeAndDeserialize() throws Exception { - SnapshotManifest manifest = new SnapshotManifest(Arrays.asList("db1", "db2", "db3"), new DurationSpec("2m"), Instant.ofEpochMilli(currentTimeMillis())); + SnapshotManifest manifest = new SnapshotManifest(Arrays.asList("db1", "db2", "db3"), new DurationSpec.IntSecondsBound("2m"), Instant.ofEpochMilli(currentTimeMillis())); File manifestFile = new File(tempFolder.newFile("manifest.json")); manifest.serializeToJsonFile(manifestFile); diff --git a/test/unit/org/apache/cassandra/streaming/StreamManagerTest.java b/test/unit/org/apache/cassandra/streaming/StreamManagerTest.java index b1168d6ea9..0ea7e7f663 100644 --- a/test/unit/org/apache/cassandra/streaming/StreamManagerTest.java +++ b/test/unit/org/apache/cassandra/streaming/StreamManagerTest.java @@ -34,14 +34,15 @@ public class StreamManagerTest { private static double defaultStreamThroughputMebibytesPerSec; private static double defaultInterDCStreamThroughputMebibytesPerSec; - private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec - .megabitsPerSecondInMebibytesPerSecond(Integer.MAX_VALUE) - .toMebibytesPerSecond(); + private static final int MAX_INT_CONFIG_VALUE = Integer.MAX_VALUE - 1; + private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec.IntMebibytesPerSecondBound + .megabitsPerSecondInMebibytesPerSecond(MAX_INT_CONFIG_VALUE) + .toMebibytesPerSecond(); private static double defaultEntireSSTableStreamThroughputMebibytesPerSec; private static double defaultEntireSSTableInterDCStreamThroughputMebibytesPerSec; - final double MEBIBYTES_PER_MEGABIT = 0.119209289550781; + private static final double MEBIBYTES_PER_MEGABIT = 0.119209289550781; @BeforeClass public static void setupClass() @@ -67,7 +68,7 @@ public class StreamManagerTest assertEquals(500 * MEBIBYTES_PER_MEGABIT * BYTES_PER_MEBIBYTE, StreamRateLimiter.getRateLimiterRateInBytes(), 0); // Max positive value check - StorageService.instance.setStreamThroughputMbitPerSec(Integer.MAX_VALUE); + StorageService.instance.setStreamThroughputMbitPerSec(MAX_INT_CONFIG_VALUE); assertEquals(INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * BYTES_PER_MEBIBYTE, StreamRateLimiter.getRateLimiterRateInBytes(), 0.04); // Zero value check @@ -86,8 +87,8 @@ public class StreamManagerTest assertEquals(1500d * BYTES_PER_MEBIBYTE, Math.round(StreamRateLimiter.getEntireSSTableRateLimiterRateInBytes()), 0); // Max positive value check - StorageService.instance.setEntireSSTableStreamThroughputMebibytesPerSec(Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE * BYTES_PER_MEBIBYTE, StreamRateLimiter.getEntireSSTableRateLimiterRateInBytes(), 0); + StorageService.instance.setEntireSSTableStreamThroughputMebibytesPerSec(MAX_INT_CONFIG_VALUE); + assertEquals((MAX_INT_CONFIG_VALUE) * BYTES_PER_MEBIBYTE, StreamRateLimiter.getEntireSSTableRateLimiterRateInBytes(), 0); // Zero value check StorageService.instance.setEntireSSTableStreamThroughputMebibytesPerSec(0); @@ -105,7 +106,7 @@ public class StreamManagerTest assertEquals(200 * MEBIBYTES_PER_MEGABIT * BYTES_PER_MEBIBYTE, StreamRateLimiter.getInterDCRateLimiterRateInBytes(), 0); // Max positive value check - StorageService.instance.setInterDCStreamThroughputMbitPerSec(Integer.MAX_VALUE); + StorageService.instance.setInterDCStreamThroughputMbitPerSec(MAX_INT_CONFIG_VALUE); assertEquals(INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * BYTES_PER_MEBIBYTE, StreamRateLimiter.getInterDCRateLimiterRateInBytes(), 0.04); // Zero value check @@ -124,8 +125,8 @@ public class StreamManagerTest assertEquals(1200.0d * BYTES_PER_MEBIBYTE, StreamRateLimiter.getEntireSSTableInterDCRateLimiterRateInBytes(), 0); // Max positive value check - StorageService.instance.setEntireSSTableInterDCStreamThroughputMebibytesPerSec(Integer.MAX_VALUE); - assertEquals(Integer.MAX_VALUE * BYTES_PER_MEBIBYTE, StreamRateLimiter.getEntireSSTableInterDCRateLimiterRateInBytes(), 0); + StorageService.instance.setEntireSSTableInterDCStreamThroughputMebibytesPerSec(MAX_INT_CONFIG_VALUE); + assertEquals((MAX_INT_CONFIG_VALUE) * BYTES_PER_MEBIBYTE, StreamRateLimiter.getEntireSSTableInterDCRateLimiterRateInBytes(), 0); // Zero value check StorageService.instance.setEntireSSTableInterDCStreamThroughputMebibytesPerSec(0); diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetColumnIndexSizeTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetColumnIndexSizeTest.java index b5ecc2029c..2ea4e75d14 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetColumnIndexSizeTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetColumnIndexSizeTest.java @@ -66,13 +66,13 @@ public class SetGetColumnIndexSizeTest extends CQLTester @Test public void testNegative() { - assertSetInvalidColumnIndexSize("-7", "Invalid data storage: value must be positive, but was -7", 1); + assertSetInvalidColumnIndexSize("-7", "Invalid data storage: value must be non-negative", 1); } @Test public void testInvalidValue() { - assertSetInvalidColumnIndexSize("2097152", "column_index_size must be positive value <= 2147483647B, but was 2147483648B", 2); + assertSetInvalidColumnIndexSize("2097152", "column_index_size must be positive value <= 2147483646B, but was 2147483647B", 2); } @Test diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetCompactionThroughputTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetCompactionThroughputTest.java index 604cd7b893..59137e97a2 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetCompactionThroughputTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetCompactionThroughputTest.java @@ -53,7 +53,7 @@ public class SetGetCompactionThroughputTest extends CQLTester @Test public void testMaxValue() { - assertSetGetValidThroughput(Integer.MAX_VALUE); + assertSetGetValidThroughput(Integer.MAX_VALUE - 1); } @Test diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableInterDCStreamThroughputTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableInterDCStreamThroughputTest.java index d412ab7b66..8c5d7ff87d 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableInterDCStreamThroughputTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableInterDCStreamThroughputTest.java @@ -55,7 +55,7 @@ public class SetGetEntireSSTableInterDCStreamThroughputTest extends CQLTester @Test public void testMaxValue() { - assertSetGetValidThroughput(Integer.MAX_VALUE, Integer.MAX_VALUE * StreamRateLimiter.BYTES_PER_MEBIBYTE); + assertSetGetValidThroughput(Integer.MAX_VALUE - 1, (Integer.MAX_VALUE - 1) * StreamRateLimiter.BYTES_PER_MEBIBYTE); } @Test diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableStreamThroughputTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableStreamThroughputTest.java index 10426b089a..93c31507c3 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableStreamThroughputTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetEntireSSTableStreamThroughputTest.java @@ -55,7 +55,7 @@ public class SetGetEntireSSTableStreamThroughputTest extends CQLTester @Test public void testMaxValue() { - assertSetGetValidThroughput(Integer.MAX_VALUE, Integer.MAX_VALUE * StreamRateLimiter.BYTES_PER_MEBIBYTE); + assertSetGetValidThroughput(Integer.MAX_VALUE - 1, (Integer.MAX_VALUE - 1) * StreamRateLimiter.BYTES_PER_MEBIBYTE); } @Test diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetInterDCStreamThroughputTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetInterDCStreamThroughputTest.java index 6b06c69013..81c6695dc0 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetInterDCStreamThroughputTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetInterDCStreamThroughputTest.java @@ -35,9 +35,10 @@ import static org.assertj.core.api.Assertions.withPrecision; */ public class SetGetInterDCStreamThroughputTest extends CQLTester { - private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec - .megabitsPerSecondInMebibytesPerSecond(Integer.MAX_VALUE) - .toMebibytesPerSecond(); + private static final int MAX_INT_CONFIG_VALUE = Integer.MAX_VALUE - 1; + private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec.IntMebibytesPerSecondBound + .megabitsPerSecondInMebibytesPerSecond(MAX_INT_CONFIG_VALUE) + .toMebibytesPerSecond(); @BeforeClass public static void setup() throws Exception @@ -69,7 +70,7 @@ public class SetGetInterDCStreamThroughputTest extends CQLTester @Test public void testMaxValue() { - assertSetGetValidThroughput(Integer.MAX_VALUE, INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * StreamRateLimiter.BYTES_PER_MEBIBYTE); + assertSetGetValidThroughput(MAX_INT_CONFIG_VALUE, INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * StreamRateLimiter.BYTES_PER_MEBIBYTE); } @Test diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SetGetStreamThroughputTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SetGetStreamThroughputTest.java index 7000387945..64bc5f71c6 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SetGetStreamThroughputTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SetGetStreamThroughputTest.java @@ -36,9 +36,10 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class SetGetStreamThroughputTest extends CQLTester { - private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec - .megabitsPerSecondInMebibytesPerSecond(Integer.MAX_VALUE) - .toMebibytesPerSecond(); + private static final int MAX_INT_CONFIG_VALUE = Integer.MAX_VALUE - 1; + private static final double INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES = DataRateSpec.IntMebibytesPerSecondBound + .megabitsPerSecondInMebibytesPerSecond(MAX_INT_CONFIG_VALUE) + .toMebibytesPerSecond(); @BeforeClass public static void setup() throws Exception @@ -70,7 +71,7 @@ public class SetGetStreamThroughputTest extends CQLTester @Test public void testMaxValue() { - assertSetGetValidThroughput(Integer.MAX_VALUE, INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * StreamRateLimiter.BYTES_PER_MEBIBYTE); + assertSetGetValidThroughput(MAX_INT_CONFIG_VALUE, INTEGER_MAX_VALUE_MEGABITS_IN_MEBIBYTES * StreamRateLimiter.BYTES_PER_MEBIBYTE); } @Test diff --git a/test/unit/org/apache/cassandra/transport/RateLimitingTest.java b/test/unit/org/apache/cassandra/transport/RateLimitingTest.java index fda392b898..ad4c9c1cdb 100644 --- a/test/unit/org/apache/cassandra/transport/RateLimitingTest.java +++ b/test/unit/org/apache/cassandra/transport/RateLimitingTest.java @@ -60,6 +60,8 @@ public class RateLimitingTest extends CQLTester private static final int LARGE_PAYLOAD_THRESHOLD_BYTES = 1000; private static final int OVERLOAD_PERMITS_PER_SECOND = 1; + private static final long MAX_LONG_CONFIG_VALUE = Long.MAX_VALUE - 1; + @Parameterized.Parameter public ProtocolVersion version; @@ -99,7 +101,7 @@ public class RateLimitingTest extends CQLTester } }; - ClientResourceLimits.setGlobalLimit(Long.MAX_VALUE); + ClientResourceLimits.setGlobalLimit(MAX_LONG_CONFIG_VALUE); } @Test