/*

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__ENTITY_STREAM_HPP_ )
#define _OESS_1__DB__STORAGE__ENTITY_STREAM_HPP_

#include <cpp_util_2/h/nocopy.hpp>

#include <smart_ref_3/h/smart_ref.hpp>

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

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

#include <oess_1/io/h/stream.hpp>

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

namespace oess_1 {

namespace db {

namespace storage {

//! Аналог NULL для идентификатора сущности.
const oess_1::uint_t	c_invalid_ent_id = 0;

/*
** entity_stream_t
*/

/*!
	\brief Интерфейс потока сущностей в хранилище.

	\note Методы, которые изменяют поток, должны вызываться
		только внутри транзакций.
*/
class	OESS_1__DB__TYPE	entity_stream_t
	:	private cpp_util_2::nocopy_t
	{
	public :
		virtual ~entity_stream_t();

		//! Получить идентификатор данного потока в хранилище.
		virtual oess_1::uint_t
		id() const = 0;

		//! Создать сущность указанного размера.
		/*!
			\return Возвращается идентификатор сущности.

			Значение сущности будет считываться с
			текущей позиции в ent_value.
		*/
		virtual chain_id_t
		entity_create(
			//! Значение сущности.
			oess_1::io::istream_t & ent_value,
			//! Размер сущности.
			oess_1::uint_t ent_size ) = 0;

		//! Прочитать значение сущности с указанным
		//! идентификатором.
		/*! Значение сущности будет записываться начиная
			с текущей позиции в ent_value.
		*/
		virtual void
		entity_load(
			//! Идентификатор загружаемой сущности.
			const chain_id_t & ent_id,
			//! Приемник значения сущности.
			oess_1::io::ostream_t & ent_value ) const = 0;

		//! Перезаписать значение сущности по
		//! старому идентификатору.
		/*!
			Если размер сущности изменяется, то
			модифицируется цепочка блоков, выделеная
			для сущности.

			Значение сущности будет считываться с
			текущей позиции в ent_value.
		*/
		virtual void
		entity_update(
			//! Идентификатор обновляемой сущности.
			const chain_id_t & ent_id,
			//! Значение сущности.
			oess_1::io::istream_t & ent_value,
			//! Размер сущности.
			oess_1::uint_t ent_size ) = 0;

		//! Удалить сущность.
		virtual void
		entity_destroy(
			//! Идентификатор удаляемой сущности.
			const chain_id_t & ent_id ) = 0;

		//! Уничтожить все сущности, находящиеся в потоке.
		/*!
			\since v.1.4.0
		*/
		virtual void
		entity_destroy_all() = 0;

		//! Найти следующую существующую сущность.
		/*!
			Для нахождения первой существующей сущности
			нужно указать в качестве ent_id значение
			c_invalid_ent_id.

			Если найти следующую существующую
			сущность не удается, то возвращается
			c_invalid_ent_id.
		*/
		virtual chain_id_t
		entity_find_next(
			const chain_id_t & ent_id ) const = 0;

};

//
// ref_entity_stream_t
//

SMART_REF_3_DECL_REF( entity_stream_t, class OESS_1__DB__TYPE )

//
// create_std_entity_stream
//

/*!
	\since v.1.4.0
	\brief Создать штатную реализацию интерфейса entity_stream_t.

	\return указатель на динамически созданный объект, ответственность
		за уничтожение которого несет вызывающая сторона.
*/
OESS_1__DB__FUNC(entity_stream_t *)
create_std_entity_stream(
	//! Хранилище, в котором поток сущностей физически расположен.
	chain_storage_t & storage,
	//! Идентификатор, назначенный этому потоку.
	oess_1::uint_t id,
	//! Идентификатор цепочки, в которой сохранен описатель потока.
	const chain_id_t & description_chain );

//
// create_entity_stream_description
//

/*!
	\since v.1.4.0
	\brief Создать в хранилище описание для нового потока сущностей.
*/
OESS_1__DB__FUNC(chain_id_t)
create_entity_stream_description(
	//! Хранилище, в котором поток сущностей физически расположен.
	chain_storage_t & storage );

//
// destroy_entity_stream_description
//

/*!
	\since v.1.4.0
	\brief Уничтожить описание потока сущностей, расположенное в
		указанной цепочке.
*/
OESS_1__DB__FUNC(void)
destroy_entity_stream_description(
	//! Хранилище, в котором поток сущностей физически расположен.
	chain_storage_t & storage,
	//! Идентификатор цепочки, в которой сохранен описатель потока.
	const chain_id_t & description_chain );

} /* namespace storage */

} /* namespace db */

} /* namespace oess_1 */

#endif
