/**
* Licensed 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 io.horizondb.db;
import io.horizondb.db.commitlog.CommitLog;
import io.horizondb.db.commitlog.CommitLog.SyncMode;
import io.horizondb.io.compression.CompressionType;
import io.horizondb.io.files.FileUtils;
import io.netty.util.internal.PlatformDependent;
import java.nio.file.Path;
import javax.annotation.concurrent.Immutable;
import org.apache.commons.lang.Validate;
import static io.horizondb.io.files.FileUtils.ONE_KB;
import static io.horizondb.io.files.FileUtils.ONE_MB;
import static org.apache.commons.lang.Validate.notNull;
/**
* The database configuration.
*
* @author Benjamin
*/
@Immutable
public final class Configuration {
/**
* The port on which the server is listening.
*/
private final int port;
/**
* The data directory.
*/
private final Path dataDirectory;
/**
* The size in bytes of the in memory time series.
*/
private final int memTimeSeriesSize;
/**
* The commit log directory.
*/
private final Path commitLogDirectory;
/**
* The size in bytes of the commit log segments.
*/
private final long commitLogSegmentSize;
/**
* The maximum number of commit log segments.
*/
private final int maximumNumberOfCommitLogSegments;
/**
* Specify how the commit log will sync data to the disk.
*/
private final CommitLog.SyncMode commitLogSyncMode;
/**
* The window of time in milliseconds during which the commit log will wait for more writes before flushing
* the data to the disk.
*/
private final long commitLogBatchWindowInMillis;
/**
* The period of time in milliseconds at which the commit log will flush data to the disk.
*/
private final long commitLogFlushPeriodInMillis;
/**
* The time to wait for shutdown in seconds.
*/
private final int shutdownWaitingTimeInSeconds;
/**
* The maximum size of the database cache.
*/
private final long databaseCacheMaximumSize;
/**
* The maximum size of the time series cache.
*/
private final long timeSeriesCacheMaximumSize;
/**
* The maximum amount of memory that is allowed to be used by the <code>MemTimeSeries</code>.
*/
private final long maximumMemoryUsageByMemTimeSeries;
/**
* The idle time in second after which a <code>MemTimeSeries</code> must be flushed to the disk.
*/
private final long memTimeSeriesIdleTimeInSecond;
/**
* The concurrency level used for the caches.
*/
private final int cachesConcurrencyLevel;
/**
* The size in bytes of the partitions blocks.
*/
private final int blockSizeInBytes;
/**
* The type of compression used by this time series.
*/
private final CompressionType compressionType;
/**
* Creates a new <code>Builder</code> instance.
*
* @return a new <code>Builder</code> instance.
*/
public static Builder newBuilder() {
return new Builder();
}
/**
* Creates a new <code>Configuration</code> instance from the specified <code>Builder</code>.
*
* @param builder the builder.
*/
private Configuration(Builder builder) {
this.port = builder.port;
this.dataDirectory = builder.dataDirectory;
this.commitLogDirectory = builder.commitLogDirectory;
this.commitLogSyncMode = builder.commitLogSyncMode;
this.commitLogSegmentSize = builder.commitLogSegmentSize;
this.maximumNumberOfCommitLogSegments = builder.maximumNumberOfCommitLogSegments;
this.commitLogFlushPeriodInMillis = builder.commitLogFlushPeriodInMillis;
this.commitLogBatchWindowInMillis = builder.commitLogBatchWindowInMillis;
this.databaseCacheMaximumSize = builder.databaseCacheMaximumSize;
this.memTimeSeriesSize = builder.memTimeSeriesSize;
this.shutdownWaitingTimeInSeconds = builder.shutdownWaitingTimeInSeconds;
this.maximumMemoryUsageByMemTimeSeries = builder.maximumMemoryUsageByMemTimeSeries;
this.memTimeSeriesIdleTimeInSecond = builder.memTimeSeriesIdleTimeInSecond;
this.blockSizeInBytes = builder.blockSizeInBytes;
this.compressionType = builder.compressionType;
this.timeSeriesCacheMaximumSize = builder.timeSeriesCacheMaximumSize;
this.cachesConcurrencyLevel = builder.cachesConcurrencyLevel;
}
/**
* Returns the port on which the server is listening.
*
* @return the port on which the server is listening.
*/
public int getPort() {
return this.port;
}
/**
* Returns the directory where the data are stored.
*
* @return the directory where the data are stored.
*/
public Path getDataDirectory() {
return this.dataDirectory;
}
/**
* Returns the size in bytes of the commit log segments.
*
* @return the size in bytes of the commit log segments.
*/
public long getCommitLogSegmentSize() {
return this.commitLogSegmentSize;
}
/**
* Returns the commit log directory.
*
* @return the commit log directory.
*/
public Path getCommitLogDirectory() {
return this.commitLogDirectory;
}
/**
* Returns the mode used by the commit log to sync the data to the disk.
*
* @return the mode used by the commit log to sync the data to the disk.
*/
public CommitLog.SyncMode getCommitLogSyncMode() {
return this.commitLogSyncMode;
}
/**
* Returns the maximum number of commit log segments.
*
* @return the maximum number of commit log segments.
*/
public int getMaximumNumberOfCommitLogSegments() {
return this.maximumNumberOfCommitLogSegments;
}
/**
* Returns the period of time in milliseconds at which the commit log will flush data to the disk.
*
* @return the period of time in milliseconds at which the commit log will flush data to the disk.
*/
public long getCommitLogFlushPeriodInMillis() {
return this.commitLogFlushPeriodInMillis;
}
/**
* Returns window of time in milliseconds during which the commit log will wait for more writes before flushing
* the data to the disk.
*
* @return the window of time in milliseconds during which the commit log will wait for more writes before flushing
* the data to the disk
*/
public long getCommitLogBatchWindowInMillis() {
return this.commitLogBatchWindowInMillis;
}
/**
* Returns the maximum size of the database cache.
*
* @return the maximum size of the database cache.
*/
public long getDatabaseCacheMaximumSize() {
return this.databaseCacheMaximumSize;
}
/**
* Returns the maximum size of the time series cache.
*
* @return the maximum size of the time series cache.
*/
public long getTimeSeriesCacheMaximumSize() {
return this.timeSeriesCacheMaximumSize;
}
/**
* Returns the maximum amount of memory that can be used by the time series.
*
* @return the maximum amount of memory that can be used by the time series.
*/
public long getMaximumMemoryUsageByMemTimeSeries() {
return this.maximumMemoryUsageByMemTimeSeries;
}
/**
* Returns the life time of the <code>MemTimeSeries</code>. <code>MemTimeSeries</code> that reach that life time
* will be flushed to the disk.
*
* @return the maximum amount of memory that can be used by the time series.
*/
public long getMemTimeSeriesIdleTimeInSeconds() {
return this.memTimeSeriesIdleTimeInSecond;
}
/**
* Returns the size in bytes of the in memory time series.
*
* @return the size in bytes of the in memory time series.
*/
public int getMemTimeSeriesSize() {
return this.memTimeSeriesSize;
}
/**
* Returns the time to wait for shutdown in seconds.
*
* @return the time to wait for shutdown in seconds.
*/
public int getShutdownWaitingTimeInSeconds() {
return this.shutdownWaitingTimeInSeconds;
}
/**
* Returns the concurrency level to use for the caches.
*
* @return the concurrency level to use for the caches.
*/
public int getCachesConcurrencyLevel() {
return this.cachesConcurrencyLevel;
}
/**
* Returns the default compression type used by the time series.
*
* @return the default compression type used by the time series
*/
public CompressionType getCompressionType() {
return this.compressionType;
}
/**
* Returns the partition block size in bytes.
*
* @return the partition block size in bytes.
*/
public int getBlockSizeInBytes() {
return this.blockSizeInBytes;
}
/**
* The builder for <code>Configuration</code> instance.
*
* @author benjamin
*/
public static final class Builder {
/**
* The default compression type used by the time series
*/
private static final CompressionType DEFAULT_COMPRESSION_TYPE = CompressionType.LZ4;
/**
* The default size in bytes of the partition blocks.
*/
private static final int DEFAULT_BLOCK_SIZE_IN_BYTES = 64 * FileUtils.ONE_KB;
/**
* The default mode used by the commit log to sync data to the disk.
*/
private static final SyncMode DEFAULT_COMMITLOG_SYNC_MODE = CommitLog.SyncMode.BATCH;
/**
* The default concurrency level for the caches.
*/
private static final int DEFAULT_CACHES_CONCURRENCY_LEVEL = 4;
/**
* The default idle time of a <code>MemTimeSerie</code> before it must be flushed to the disk.
*/
private static final int DEFAULT_MEMTIMESERIES_IDLE_TIME_IN_SECOND = 2 * 60 * 60;
/**
* The default maximum size of the time series cache.
*/
private static final int DEFAULT_TIMESERIES_CACHE_MAX_SIZE = 200;
/**
* The default size of the in memory time series.
*/
private static final int DEFAULT_MEMTIMESERIES_SIZE = ONE_MB;
/**
* The port by default.
*/
private static final int DEFAULT_PORT = 8553;
/**
* The default period of time in millisecond at which the commit-log will flush the data to the disk.
*/
private static final int DEFAULT_COMMITLOG_FLUSH_PERIOD = 1000;
/**
* The default commit log batch window.
*/
private static final int DEFAULT_COMMITLOG_BATCH_WINDOW = 50;
/**
* The default size for the database cache.
*/
private static final long DEFAULT_DATABASE_CACHE_MAX_SIZE = 20;
/**
* The port on which the server is listening.
*/
private int port = DEFAULT_PORT;
/**
* The size in bytes of the in memory time series.
*/
private int memTimeSeriesSize = DEFAULT_MEMTIMESERIES_SIZE;
/**
* The data directory.
*/
private Path dataDirectory;
/**
* The commit log directory.
*/
private Path commitLogDirectory;
/**
* Specify how the commit log will sync data to the disk.
*/
private CommitLog.SyncMode commitLogSyncMode = DEFAULT_COMMITLOG_SYNC_MODE;
/**
* The maximum number of commit log segments.
*/
private int maximumNumberOfCommitLogSegments = getDefaultMaximumNumberOfSegments();
/**
* The size in bytes of the commit log segments.
*/
private long commitLogSegmentSize = getDefaultSegmentSize();
/**
* The period of time in milliseconds at which the commit log will flush data to the disk.
*/
private long commitLogFlushPeriodInMillis = DEFAULT_COMMITLOG_FLUSH_PERIOD;
/**
* The window of time in milliseconds during which the commit log will wait for more writes before flushing
* the data to the disk.
*/
private long commitLogBatchWindowInMillis = DEFAULT_COMMITLOG_BATCH_WINDOW;
/**
* The maximum size of the database cache.
*/
private long databaseCacheMaximumSize = DEFAULT_DATABASE_CACHE_MAX_SIZE;
/**
* The time to wait for shutdown in seconds.
*/
private int shutdownWaitingTimeInSeconds = 30;
/**
* The maximum size of the time series cache.
*/
private long timeSeriesCacheMaximumSize = DEFAULT_TIMESERIES_CACHE_MAX_SIZE;
/**
* The maximum amount of memory in bytes that is allowed to be used by the <code>MemTimeSeries</code>.
*/
private long maximumMemoryUsageByMemTimeSeries = getDefaultMaxMemoryUsageByMemTimeSeries();
/**
* The time in second after which an idle <code>MemTimeSeries</code> must be flushed to the disk.
*/
private long memTimeSeriesIdleTimeInSecond = DEFAULT_MEMTIMESERIES_IDLE_TIME_IN_SECOND;
/**
* The concurrency level used for the caches.
*/
private int cachesConcurrencyLevel = DEFAULT_CACHES_CONCURRENCY_LEVEL;
/**
* The size in bytes of the partitions blocks.
*/
private int blockSizeInBytes = DEFAULT_BLOCK_SIZE_IN_BYTES;
/**
* The default type of compression used by the time series.
*/
private CompressionType compressionType = DEFAULT_COMPRESSION_TYPE;
/**
* Specifies the port on which the database server is listening.
*
* @param port the directory to use to store the commit logs.
* @return this <code>Builder</code>.
*/
public Builder port(int port) {
this.port = port;
return this;
}
/**
* Specify the size in KB of the in memory time series.
*
* @param memTimeSeriesSizeInKB the size in KB of the in memory time series.
* @return this <code>builder</code>.
*/
public Builder memTimeSeriesSizeInKB(int memTimeSeriesSizeInKB) {
return memTimeSeriesSize(memTimeSeriesSizeInKB * ONE_KB);
}
/**
* Specify the size in bytes of the in memory time series.
*
* @param memTimeSeriesSize the size in bytes of the in memory time series.
* @return this <code>builder</code>.
*/
public Builder memTimeSeriesSize(int memTimeSeriesSize) {
this.memTimeSeriesSize = memTimeSeriesSize;
return this;
}
/**
* Specifies the data directory.
*
* @param directory the directory to use to store data.
* @return this <code>Builder</code>.
*/
public Builder dataDirectory(Path directory) {
this.dataDirectory = directory;
return this;
}
/**
* Specifies the commit log directory.
*
* @param directory the directory to use to store the commit logs.
* @return this <code>Builder</code>.
*/
public Builder commitLogDirectory(Path directory) {
this.commitLogDirectory = directory;
return this;
}
/**
* Specifies mode used by the commit log to sync the data to the disk.
*
* @param commitLogSyncMode the mode used by the commit log to sync the data to the disk
* @return this <code>Builder</code>.
*/
public Builder commitLogSyncMode(CommitLog.SyncMode commitLogSyncMode) {
this.commitLogSyncMode = commitLogSyncMode;
return this;
}
/**
* Specifies the maximum number of commit log segments.
*
* @param maximumNumberOfCommitLogSegments the maximum number of commit log segments.
* @return this <code>Builder</code>.
*/
public Builder maximumNumberOfCommitLogSegments(int maximumNumberOfCommitLogSegments) {
Validate.isTrue(maximumNumberOfCommitLogSegments >= 3,
"The maximum number of segments must be greater or equals to 3.");
this.maximumNumberOfCommitLogSegments = maximumNumberOfCommitLogSegments;
return this;
}
/**
* Specifies the size in MB of the commit log segments.
*
* @param commitLogSegmentSize the size in MB of the commit log segments.
* @return this <code>Builder</code>.
*/
public Builder commitLogSegmentSizeInMB(long commitLogSegmentSizeInMB) {
return commitLogSegmentSize(commitLogSegmentSizeInMB * ONE_MB);
}
/**
* Specifies the window of time in milliseconds during which the commit log will wait for more writes before
* flushing the data to the disk.
*
* @param commitLogBatchWindowInMillis the window of time in milliseconds during which the commit log will
* wait for more writes before flushing the data to the disk
* @return this <code>Builder</code>.
*/
public Builder commitLogBatchWindowInMillis(long commitLogBatchWindowInMillis) {
Validate.isTrue(commitLogBatchWindowInMillis > 0, "The commit log batch window must be greater than 0.");
this.commitLogBatchWindowInMillis = commitLogBatchWindowInMillis;
return this;
}
/**
* Specifies the size in bytes of the commit log segments.
*
* @param commitLogSegmentSize the size in bytes of the commit log segments.
* @return this <code>Builder</code>.
*/
public Builder commitLogSegmentSize(long commitLogSegmentSize) {
this.commitLogSegmentSize = commitLogSegmentSize;
return this;
}
/**
* Specifies the period of time in milliseconds at which the commit log will flush data to the disk.
*
* @param commitLogFlushPeriodInMillis the period of time in milliseconds at which the commit log will flush
* data to the disk.
* @return this <code>Builder</code>.
*/
public Builder commitLogFlushPeriodInMillis(long commitLogFlushPeriodInMillis) {
Validate.isTrue(commitLogFlushPeriodInMillis > 0, "The commit log flush period must be greater than 0.");
this.commitLogFlushPeriodInMillis = commitLogFlushPeriodInMillis;
return this;
}
/**
* Specifies the maximum number of cached databases.
*
* @param databaseCacheMaximumSize the maximum number of cached databases.
* @return this <code>Builder</code>.
*/
public Builder databaseCacheMaximumSize(long databaseCacheMaximumSize) {
Validate.isTrue(databaseCacheMaximumSize > 0, "The database cache maximum size must be greater than 0.");
this.databaseCacheMaximumSize = databaseCacheMaximumSize;
return this;
}
/**
* Specifies the time to wait for shutdown in seconds.
*
* @param shutdownWaitingTimeInSeconds Specify the time to wait for shutdown in seconds.
* @return this <code>Builder</code>.
*/
public Builder shutdownWaitingTimeInSeconds(int shutdownWaitingTimeInSeconds) {
this.shutdownWaitingTimeInSeconds = shutdownWaitingTimeInSeconds;
return this;
}
/**
* Specifies the maximum size of the time series cache.
*
* @param timeSeriesCacheMaximumSize the maximum size of the time series cache.
* @return this <code>Builder</code>.
*/
public Builder timeSeriesCacheMaximumSize(long timeSeriesCacheMaximumSize) {
this.timeSeriesCacheMaximumSize = timeSeriesCacheMaximumSize;
return this;
}
/**
* Specify the maximum amount of memory in bytes that is allowed to be used by the <code>MemTimeSeries</code>.
*
* @param maximumMemoryUsageByMemTimeSeries the maximum amount of memory in bytes that is allowed to be used by
* the <code>MemTimeSeries</code>.
* @return this <code>Builder</code>.
*/
public Builder maximumMemoryUsageByMemTimeSeries(int maximumMemoryUsageByMemTimeSeries) {
this.maximumMemoryUsageByMemTimeSeries = maximumMemoryUsageByMemTimeSeries;
return this;
}
/**
* Specify the maximum amount of memory in MB that is allowed to be used by the <code>MemTimeSeries</code>.
*
* @param maximumMemoryUsageByMemTimeSeriesInMB the maximum amount of memory in bytes that is allowed to be used
* by the <code>MemTimeSeries</code>.
* @return this <code>Builder</code>.
*/
public Builder maximumMemoryUsageByMemTimeSeriesInMB(int maximumMemoryUsageByMemTimeSeriesInMB) {
this.maximumMemoryUsageByMemTimeSeries = maximumMemoryUsageByMemTimeSeriesInMB * ONE_MB;
return this;
}
/**
* Specify the time in second after which a <code>MemTimeSeries</code> must be flushed to the disk.
*
* @param memTimeSeriesIdleTimeInSecond the time in second after which a <code>MemTimeSeries</code> must be
* flushed to the disk.
* @return this <code>Builder</code>.
*/
public Builder memTimeSeriesIdleTimeInSecond(int memTimeSeriesIdleTimeInSecond) {
this.memTimeSeriesIdleTimeInSecond = memTimeSeriesIdleTimeInSecond;
return this;
}
/**
* Specify the concurrency level for the caches.
*
* @param cachesConcurrencyLevel the concurrency level for the caches.
* @return this <code>Builder</code>.
*/
public Builder cachesConcurrencyLevel(int cachesConcurrencyLevel) {
this.cachesConcurrencyLevel = cachesConcurrencyLevel;
return this;
}
/**
* Specify the default partition block size in bytes.
*
* @param blockSizeInBytes the default partition block size in bytes.
* @return this <code>Builder</code>.
*/
public Builder blockSizeInBytes(int blockSizeInBytes) {
this.blockSizeInBytes = blockSizeInBytes;
return this;
}
/**
* Sets the default type of compression used by the time series.
*
* @param compressionType the default type of compression used by the time series.
* @return this <code>Builder</code>.
*/
public Builder compressionType(CompressionType compressionType) {
notNull(compressionType, "the compressionType parameter must not be null.");
this.compressionType = compressionType;
return this;
}
/**
* Builds a new <code>Configuration</code> instance.
*
* @return a new <code>Configuration</code> instance.
*/
public Configuration build() {
return new Configuration(this);
}
/**
* Must not be instantiated.
*/
private Builder() {
}
/**
* Returns the default size for the commit log segments.
*
* @return the default size for the commit log segments.
*/
private static int getDefaultSegmentSize() {
if (PlatformDependent.bitMode() == 32) {
return 8 * ONE_MB;
}
return 32 * ONE_MB;
}
/**
* Returns the default maximum number of commit log segments.
*
* @return the default maximum number of commit log segments.
*/
private static int getDefaultMaximumNumberOfSegments() {
if (PlatformDependent.bitMode() == 32) {
return 4;
}
return 32;
}
/**
* Return the default amount of memory that can be used by all the memory time series.
*
* @return the default amount of memory that can be used by all the memory time series.
*/
private static long getDefaultMaxMemoryUsageByMemTimeSeries() {
long maxMemory = Runtime.getRuntime().maxMemory();
return maxMemory / 4;
}
}
}