/*

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.

*/

/*!
	\file
	\brief Тип оглавления хранилища потоков.
*/
#if !defined( _OESS_1__DB__STORAGE__IMPL__STREAM_STORAGE_DIR_HPP_ )
#define _OESS_1__DB__STORAGE__IMPL__STREAM_STORAGE_DIR_HPP_

#include <map>
#include <set>

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

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

#include <oess_1/db/storage/h/chain_id.hpp>

namespace oess_1 {

namespace db {

namespace storage {

namespace impl {

//
// stream_storage_dir_item_t
//

/*!
	\since v.1.4.0
	\brief Элемент оглавления хранилища потоков.
*/
class	stream_storage_dir_item_t
	:	public oess_1::stdsn::serializable_t
	{
		typedef oess_1::stdsn::serializable_t base_type_t;
		OESS_SERIALIZER( stream_storage_dir_item_t )

	public :
		//! Конструктор по-умолчанию.
		stream_storage_dir_item_t();
		//! Полностью инициализирующий конструктор.
		stream_storage_dir_item_t(
			//! Идентификатор потока.
			const oess_1::uint_t & id,
			//! Идентификатор цепочки с описанием потока.
			const chain_id_t & description_chain );
		//! Конструктор копирования.
		stream_storage_dir_item_t(
			const stream_storage_dir_item_t & o );
		virtual ~stream_storage_dir_item_t();

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

		//! Получить идентификатор потока.
		oess_1::uint_t
		id() const;

		//! Получить идентификатор цепочки с описанием потока.
		const chain_id_t &
		description_chain() const;

	private :
		//! Идентификатор потока.
		oess_1::uint_t	m_id;
		//! Идентификатор цепочки с описанием потока.
		chain_id_t m_description_chain;
	};

//
// stream_storage_dir_t
//

/*!
	\since v.1.4.0
	\brief Оглавление хранилища потоков.
*/
class	stream_storage_dir_t
	:	public oess_1::stdsn::serializable_t
	{
		typedef oess_1::stdsn::serializable_t base_type_t;
		OESS_SERIALIZER( stream_storage_dir_t )

	public :
		//! Конструктор по-умолчанию.
		stream_storage_dir_t();
		//! Конструктор копирования.
		stream_storage_dir_t(
			const stream_storage_dir_t & o );
		virtual ~stream_storage_dir_t();

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

		//! Выделить идентификатор для нового потока.
		oess_1::uint_t
		allocate_id();

		//! Создать описание потока в оглавлении.
		/*!
			\throw oess_1::logic_ex_t, если поток с таким именем
				уже существует.
		*/
		void
		add(
			//! Имя создаваемого потока.
			const std::string & name,
			//! Идентификатор создаваемого потока.
			const oess_1::uint_t & id,
			//! Идентификатор цепочки, в которой сохранено
			//! описание потока.
			const chain_id_t & description_chain );

		//! Удалить описание потока из оглавления.
		/*!
			\throw oess_1::logic_ex_t, если потока с таким именем
				не существует.
		*/
		void
		destroy(
			//! Имя уничтожаемого потока.
			const std::string & name );

		//! Найти идентификатор потока по имени.
		/*!
			\throw oess_1::logic_ex_t, если потока с таким именем
				не существует.
		*/
		oess_1::uint_t
		find_id(
			const std::string & name ) const;

		//! Проверить существование потока с указанным именем.
		/*!
			\return true, если поток существует.
		*/
		bool
		is_exists(
			const std::string & name ) const;

		//! Получить имена всех существующих потоков.
		std::set< std::string >
		names() const;

		//! Получить идентификатор потока и идентификатор цепочки
		//! описателя потока по имени потока.
		/*!
			\throw oess_1::logic_ex_t, если потока с таким именем
				не существует.
		*/
		const stream_storage_dir_item_t &
		item(
			const std::string & name ) const;

	private :
		//! Тип карты описаний потоков.
		typedef std::map< std::string,
						stream_storage_dir_item_t >
				dir_t;

		//! Описания существующих потоков.
		dir_t	m_dir;

		//! Счетчик идентификаторов потоков.
		/*!
			Инкрементируется при каждом обращении к allocate_id().
		*/
		oess_1::uint_t	m_id;

	/*! \name Поиск элемента, который обязательно должен был
		существовать в оглавлении. Если элемент на находится, то
		порождается исключение.
		\{ */
		dir_t::iterator
		locate_existent_item(
			const std::string & name );
		dir_t::const_iterator
		locate_existent_item(
			const std::string & name ) const;
	/*! \} */
	};

} /* namespace impl */

} /* namespace storage */

} /* namespace db */

} /* namespace oess_1 */

#endif
