/*
 * 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.flink.contrib.streaming.state;

import org.rocksdb.BlockBasedTableConfig;
import org.rocksdb.ColumnFamilyOptions;
import org.rocksdb.CompactionStyle;
import org.rocksdb.DBOptions;
import org.rocksdb.StringAppendOperator;

/**
 * The {@code PredefinedOptions} are configuration settings for the {@link RocksDBStateBackend}. 
 * The various pre-defined choices are configurations that have been empirically
 * determined to be beneficial for performance under different settings.
 * 
 * <p>Some of these settings are based on experiments by the Flink community, some follow
 * guides from the RocksDB project.
 */
public enum PredefinedOptions {

	/**
	 * Default options for all settings, except that writes are not forced to the disk.
	 * 
	 * <p>Note: Because Flink does not rely on RocksDB data on disk for recovery,
	 * there is no need to sync data to stable storage.
	 */
	DEFAULT {

		@Override
		public DBOptions createDBOptions() {
			return new DBOptions()
					.setUseFsync(false)
					.setDisableDataSync(true);
		}

		@Override
		public ColumnFamilyOptions createColumnOptions() {
			return new ColumnFamilyOptions()
					.setMergeOperator(new StringAppendOperator());
		}
	},

	/**
	 * Default options as defined by RocksDB version 4.5.1. This options are present to allow
	 * reproducing the memory usage behavior from Flink versions 1.0.x and 1.1.x. 
	 *
	 * @deprecated These options are only used to make Flink 1.1.4 (updated RocksDB dependency due
	 *             to critical bug fixes in RocksDB) behave similar to Flink 1.1.3 and prior versions.
	 *             This option will not be present in Flink 1.2.0 and upwards.
	 */
	@Deprecated
	DEFAULT_ROCKS_4_5_1 {

		@Override
		public DBOptions createDBOptions() {
			return new DBOptions()
					.setUseFsync(false)
					.setDisableDataSync(true)
					.setTableCacheNumshardbits(4);
		}

		@Override
		public ColumnFamilyOptions createColumnOptions() {
			return new ColumnFamilyOptions()
					.setMergeOperator(new StringAppendOperator())
					.setWriteBufferSize(4194304)
					.setTargetFileSizeBase(2097152)
					.setMaxBytesForLevelBase(10485760);
		}
	},

	/**
	 * Pre-defined options for regular spinning hard disks.
	 * 
	 * <p>This constant configures RocksDB with some options that lead empirically
	 * to better performance when the machines executing the system use
	 * regular spinning hard disks.
	 * 
	 * <p>The following options are set:
	 * <ul>
	 *     <li>setCompactionStyle(CompactionStyle.LEVEL)</li>
	 *     <li>setLevelCompactionDynamicLevelBytes(true)</li>
	 *     <li>setIncreaseParallelism(4)</li>
	 *     <li>setUseFsync(false)</li>
	 *     <li>setDisableDataSync(true)</li>
	 *     <li>setMaxOpenFiles(-1)</li>
	 * </ul>
	 * 
	 * <p>Note: Because Flink does not rely on RocksDB data on disk for recovery,
	 * there is no need to sync data to stable storage.
	 */
	SPINNING_DISK_OPTIMIZED {

		@Override
		public DBOptions createDBOptions() {

			return new DBOptions()
					.setIncreaseParallelism(4)
					.setUseFsync(false)
					.setDisableDataSync(true)
					.setMaxOpenFiles(-1);
		}

		@Override
		public ColumnFamilyOptions createColumnOptions() {
			return new ColumnFamilyOptions()
					.setMergeOperator(new StringAppendOperator())
					.setCompactionStyle(CompactionStyle.LEVEL)
					.setLevelCompactionDynamicLevelBytes(true);
		}
	},

	/**
	 * Pre-defined options for better performance on regular spinning hard disks,
	 * at the cost of a higher memory consumption.
	 *
	 * <p><b>NOTE: These settings will cause RocksDB to consume a lot of memory for
	 * block caching and compactions. If you experience out-of-memory problems related to,
	 * RocksDB, consider switching back to {@link #SPINNING_DISK_OPTIMIZED}.</b></p>
	 *
	 * <p>The following options are set:
	 * <ul>
	 *     <li>setLevelCompactionDynamicLevelBytes(true)</li>
	 *     <li>setTargetFileSizeBase(256 MBytes)</li>
	 *     <li>setMaxBytesForLevelBase(1 GByte)</li>
	 *     <li>setWriteBufferSize(64 MBytes)</li>
	 *     <li>setIncreaseParallelism(4)</li>
	 *     <li>setMinWriteBufferNumberToMerge(3)</li>
	 *     <li>setMaxWriteBufferNumber(4)</li>
	 *     <li>setUseFsync(false)</li>
	 *     <li>setMaxOpenFiles(-1)</li>
	 *     <li>BlockBasedTableConfig.setBlockCacheSize(256 MBytes)</li>
	 *     <li>BlockBasedTableConfigsetBlockSize(128 KBytes)</li>
	 * </ul>
	 * 
	 * <p>Note: Because Flink does not rely on RocksDB data on disk for recovery,
	 * there is no need to sync data to stable storage.
	 */
	SPINNING_DISK_OPTIMIZED_HIGH_MEM {

		@Override
		public DBOptions createDBOptions() {

			return new DBOptions()
					.setIncreaseParallelism(4)
					.setUseFsync(false)
					.setDisableDataSync(true)
					.setMaxOpenFiles(-1);
		}

		@Override
		public ColumnFamilyOptions createColumnOptions() {

			final long blockCacheSize = 256 * 1024 * 1024;
			final long blockSize = 128 * 1024;
			final long targetFileSize = 256 * 1024 * 1024;
			final long writeBufferSize = 64 * 1024 * 1024;

			return new ColumnFamilyOptions()
					.setMergeOperator(new StringAppendOperator())
					.setCompactionStyle(CompactionStyle.LEVEL)
					.setLevelCompactionDynamicLevelBytes(true)
					.setTargetFileSizeBase(targetFileSize)
					.setMaxBytesForLevelBase(4 * targetFileSize)
					.setWriteBufferSize(writeBufferSize)
					.setMinWriteBufferNumberToMerge(3)
					.setMaxWriteBufferNumber(4)
					.setTableFormatConfig(
							new BlockBasedTableConfig()
									.setBlockCacheSize(blockCacheSize)
									.setBlockSize(blockSize)
					);
		}
	},
	
	/**
	 * Pre-defined options for Flash SSDs.
	 *
	 * <p>This constant configures RocksDB with some options that lead empirically
	 * to better performance when the machines executing the system use SSDs.
	 * 
	 * <p>The following options are set:
	 * <ul>
	 *     <li>setIncreaseParallelism(4)</li>
	 *     <li>setUseFsync(false)</li>
	 *     <li>setDisableDataSync(true)</li>
	 *     <li>setMaxOpenFiles(-1)</li>
	 * </ul>
	 * 
	 * <p>Note: Because Flink does not rely on RocksDB data on disk for recovery,
	 * there is no need to sync data to stable storage.
	 */
	FLASH_SSD_OPTIMIZED {

		@Override
		public DBOptions createDBOptions() {
			return new DBOptions()
					.setIncreaseParallelism(4)
					.setUseFsync(false)
					.setDisableDataSync(true)
					.setMaxOpenFiles(-1);
		}

		@Override
		public ColumnFamilyOptions createColumnOptions() {
			return new ColumnFamilyOptions()
					.setMergeOperator(new StringAppendOperator());
		}
	};
	
	// ------------------------------------------------------------------------

	/**
	 * Creates the {@link DBOptions}for this pre-defined setting.
	 * 
	 * @return The pre-defined options object. 
	 */
	public abstract DBOptions createDBOptions();

	/**
	 * Creates the {@link org.rocksdb.ColumnFamilyOptions}for this pre-defined setting.
	 *
	 * @return The pre-defined options object.
	 */
	public abstract ColumnFamilyOptions createColumnOptions();

}
