/*

Copyright (c) 2002-2005, Yauheni Akhotnikau
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

- The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.

*/

/*!
	\since v.1.4.0
	\file
	\brief Конфигурация для хранилища цепочек.
*/

#if !defined( _OESS_1__DB__STORAGE__CONFIG_HPP_ )
#define _OESS_1__DB__STORAGE__CONFIG_HPP_

#include <string>

#include <oess_1/defs/h/types.hpp>

#include <oess_1/stdsn/h/serializable.hpp>

#include <oess_1/db/h/declspec.hpp>

namespace oess_1 {

namespace db {

namespace storage {

//! \name Режим сохранения восстановочной/трассировочной информации.
//! \{

//! Тип для описания режима восстановочной информации.
/*!
	\since v.1.4.0
*/
typedef oess_1::uchar_t	trace_mode_t;

//! Режим, в котором восстановочная информация вообще не сохраняется.
/*!
	\since v.1.4.0

	Данный режим обеспечивает наивысшую скорость работы с БД, но не
	гарантирует никакой безопасности.
*/
const trace_mode_t	trace_no = 0;

//! Режим, в котором сохраняется информация только о последней транзакции.
/*!
	\since v.1.4.0

	В данном режиме в trace-файл помещается только одна транзакция -- последняя.
	При необходимости зафиксировать в БД следующую транзакцию все
	предыдущее содержимое trace-файла удаляется.

	Этот режим обеспечивает среднюю скорость работы. Но позволяет восстановить
	БД после таких сбоев, как аварийное завершение приложения, когда
	последняя транзакция еще могла быть не сохранена в БД полностью.

	Для того, чтобы иметь возможность восстановить основной файл хранилища
	после более фатальных сбоев (например, повреждения файловой системы или
	носителя) необходимо использовать внешние инструменты, т.к. аппаратное
	зеркалирование или реплицирующие файловые системы.
*/
const trace_mode_t	trace_last = 1;

//! Режим, в котором сохраняется полный след проводимых транзакций.
/*!
	\since v.1.4.0

	В данном режиме информация по каждой транзакции дописывается в конец
	trace-stream. Это позволяет восстановить весь основной файл БД
	путем воспроизведения trace-файлов. Т.е. этот режим позволяет
	восстанавливать БД после жестких сбоев при условии, что настроена
	репликация и сохранение в надежном месте trace-файлов.

	Этот режим обеспечивает наименьшую скорость работы с БД и требует
	большого объема дискового пространства.
*/
const trace_mode_t	trace_all = 2;

//! \}

//
// hard_config_t
//

/*!
	\since v.1.4.0
	\brief Конфигурационные параметры, которые не могут быть
		изменены после создания БД.
*/
class	OESS_1__DB__TYPE	hard_config_t
	:	public oess_1::stdsn::serializable_t
	{
		typedef oess_1::stdsn::serializable_t	base_type_t;
		OESS_SERIALIZER( hard_config_t )
	public :
		//! Значения основных параметров по-умолчанию.
		enum	defaults_t
			{
				//! Размер страницы хранилища по-умолчанию.
				default_page_size = 4096,
				//! Размер одного блока данных на странице по-умолчанию.
				default_chain_link_size = 256,
				//! Размер одного блока страницы для поиска изменений при
				//! формировании описания транзакции по-умолчению.
				default_trx_delta_block_size = 4096,
				//! Размер одной страницы trace-файла по-умолчанию.
				default_trace_file_page_size = 512,
				//! Режим сохранения восстановочной информации по-умолчанию.
				default_trace_mode = trace_last
			};

		//! Конструктор по-умолчанию.
		/*!
			Назначает всем параметрам значения по-умолчанию.
		*/
		hard_config_t();
		//! Полностью инициализирующий конструктор.
		/*!
			Проверяет корректность установленных значений и, если
			обнаруживает какое-то несоответствие, порождает
			oess_1::logic_ex_t.
		*/
		hard_config_t(
			//! Размер страницы хранилища в байтах.
			oess_1::uint_t page_size,
			//! Размер одного элемента цепочки (одного блока на странице).
			oess_1::uint_t chain_link_size,
			//! Размер одного блока страницы для поиска изменений при
			//! формировании описания транзакции в trace-stream.
			oess_1::uint_t trx_delta_block_size,
			//! Размер одной страницы trace-файла.
			oess_1::uint_t trace_file_page_size,
			//! Режим сохранения восстановочной информации.
			trace_mode_t trace_mode );
		//! Конструктор копирования.
		hard_config_t(
			const hard_config_t & o );
		virtual ~hard_config_t();

		//! Оператор копирования.
		hard_config_t &
		operator=( const hard_config_t & o );

		//! Размер одной страницы хранилища в байтах.
		oess_1::uint_t
		page_size() const;

		//! Размер одного звена цепочки в байтах.
		oess_1::uint_t
		chain_link_size() const;

		//! Размер одного блока страницы для поиска изменений при
		//! формировании описания транзакции в trace-stream.
		oess_1::uint_t
		trx_delta_block_size() const;

		//! Размер страницы trace-файла в байтах.
		oess_1::uint_t
		trace_file_page_size() const;

		//! Режим сохранения восстановочной информации.
		trace_mode_t
		trace_mode() const;

	private :
		//! Размер одной страницы хранилища в байтах.
		oess_1::uint_t	m_page_size;

		//! Размер одного звена цепочки в байтах.
		oess_1::uint_t	m_chain_link_size;

		//! Размер одного блока страницы для поиска изменений при
		//! формировании описания транзакции в trace-stream.
		oess_1::uint_t	m_trx_delta_block_size;

		//! Размер страницы trace-файла в байтах.
		oess_1::uint_t	m_trace_file_page_size;

		//! Режим сохранения восстановочной информации.
		trace_mode_t	m_trace_mode;
	};

//! \name Параметры компрессии данных в trace-stream.
//! \{

//! Тип для хранения режима компрессии данных в trace-stream.
/*!
	\since v.1.4.0
*/
typedef oess_1::uchar_t	trace_compression_mode_t;

//! Без компрессии.
/*!
	\since v.1.4.0

	Этот вариант может оказаться предпочтительным при
	малых объемах данных в транзакции (например, из-за малого
	размера страницы хранилища и малого размера объектов в
	хранилище) или когда данные плохо сжимаются (например,
	объекты содержат заархивированную или зашифрованную
	информацию). В этих случаях реального уменьшения образа
	транзакции в результате архивации может не быть.
*/
const trace_compression_mode_t
trace_no_compression = 0;

//! Весь образ транзакции архивируется с помощью zlib.
/*!
	\since v.1.4.0
*/
const trace_compression_mode_t
trace_zlib_compression = 1;

//! Режим компрессии, который должен использоваться по-умолчанию.
/*!
	\since v.1.4.0
*/
const trace_compression_mode_t
trace_default_compression = trace_no_compression;

//! \}

//
// config_t
//

/*!
	\since v.1.4.0
	\brief Конфигурация, необходимая для хранилища.

	Параметры деляться на неизменяемые (т.е. те, значения которых нельзя
	поменять после создания БД) и изменяемые (т.е. те, значения которых
	можно изменять между сеансами работы с БД). Неизменяемые параметры
	контролируются типом hard_config_t.
*/
class OESS_1__DB__TYPE	config_t
	{
	public :
		//! Значения изменяемых параметров по-умолчанию.
		enum	defaults_t
			{
				//! Размер кэша по-умолчанию.
				default_cache_size = 256,
				//! Максимальный объем одного trace-файла по-умолчанию.
				default_trace_file_size_limit = 10u * 1024 * 1024,
				//! Размер буфера, который использует trace-stream.
				default_trace_stream_buffered_pages = 128,
				//! Режим компрессии trace-stream.
				default_trace_stream_compression =
						trace_default_compression
			};

		//! Конструктор по-умолчанию.
		/*!
			Выставляет всем параметрам значения по-умолчанию.
		*/
		config_t();
		//! Частично инициализирующий конструктор.
		/*!
			Позволяет установить неизменяемые параметры, для остальных
			параметров используются значения по-умолчанию.
		*/
		config_t(
			const hard_config_t & o );
		~config_t();

	//! \name Методы для работы с неизменяемыми параметрами.
	//! \{
		//! Установить все неизменяемые параметры.
		void
		set_hard_config(
			const hard_config_t & config );

		//! Размер одной страницы хранилища в байтах.
		oess_1::uint_t
		page_size() const;

		//! Размер одного звена цепочки в байтах.
		oess_1::uint_t
		chain_link_size() const;

		//! Размер одного блока страницы для поиска изменений при
		//! формировании описания транзакции в trace-stream.
		oess_1::uint_t
		trx_delta_block_size() const;

		//! Размер страницы trace-файла в байтах.
		oess_1::uint_t
		trace_file_page_size() const;

		//! Режим сохранения восстановочной информации.
		trace_mode_t
		trace_mode() const;
	//! \}

	//! \name Методы для работы с изменяемыми параметрами.
	//! \{
		//! Размер кэша.
		/*!
			\return количество страниц хранилища, которые могут
				одновременно находиться в ОП.
		*/
		oess_1::uint_t
		cache_size() const;

		//! Установить размер кэша.
		void
		set_cache_size( oess_1::uint_t v );

		//! Максимальная длина одного trace-файла в байтах.
		oess_1::uint_t
		trace_file_size_limit() const;

		//! Установить длину одного trace-файла в байтах.
		void
		set_trace_file_size_limit( oess_1::uint_t v );

		//! Размер внутреннего буфера, который trace-stream использует
		//! для накопления страниц trace-файла перед записью на диск.
		/*!
			Возвращается количество страниц.
		*/
		oess_1::uint_t
		trace_stream_buffered_pages() const;

		//! Установить размер внутреннего буфера, который trace-stream
		//! использует для накопления страниц trace-файла перед записью.
		void
		set_trace_stream_buffered_pages( oess_1::uint_t v );

		//! Режим компрессии trace-stream.
		trace_compression_mode_t
		trace_compression() const;

		//! Установить режим компрессии trace-stream.
		void
		set_trace_compression(
			const trace_compression_mode_t & v );
	//! \}

	//! \name Методы для получения имен файлов хранилища.
	//! \{
		//! Создать имя конфигурационного файла указанного хранилища.
		std::string
		make_cfg_file_name(
			const std::string & physic_name ) const;

		//! Создать имя основного файла указанного хранилища.
		std::string
		make_main_file_name(
			const std::string & physic_name ) const;

		//! Создать имя "грязного" основного файла указанного хранилища.
		std::string
		make_unclear_file_name(
			const std::string & physic_name ) const;

		//! Создать имя временного основного файла указанного хранилища.
		/*! Этот файл используется при создании БД. */
		std::string
		make_tmp_main_file_name(
			const std::string & physic_name ) const;

		//! Создать имя временного "грязного" основного файла
		//! указанного хранилища.
		/*! Этот файл используется при создании БД. */
		std::string
		make_tmp_unclear_file_name(
			const std::string & physic_name ) const;
	//! \}

	private :
		//! Значения неизменяемых параметров.
		hard_config_t	m_hard_config;

	//! \name Значения изменяемых параметров.
	//! \{
		//! Размер кэша в страницах основного файла.
		oess_1::uint_t	m_cache_size;

		//! Максимальная длина trace-файла в байтах.
		oess_1::uint_t	m_trace_file_size_limit;

		//! Размер внутреннего буфера trace-stream в страницах trace-файла.
		oess_1::uint_t	m_trace_stream_buffered_pages;

		//! Режим компрессии trace-stream.
		trace_compression_mode_t	m_trace_compression;
	//! \}
	};

//
// create_cfg_file
//

/*!
	\since v.1.4.0
	\brief Сохранить конфигурацию в указанный конфигурационный файл.
*/
OESS_1__DB__FUNC(void)
create_cfg_file(
	//! Имя создаваемого конфигурационного файла.
	const std::string & file_name,
	//! Сохраняемая в файле конфигурация.
	const config_t & config );

//
// load_cfg_file
//

/*!
	\since v.1.4.0
	\brief Прочитать конфигурацию из указанного конфигурационного файла.
*/
OESS_1__DB__FUNC(config_t)
load_cfg_file(
	//! Имя конфигурационного файла.
	const std::string & file_name );

} /* namespace storage */

} /* namespace db */

} /* namespace oess_1 */

#endif

