/*!***************************************************************************

  module      : LVCSim_ObjectHandle.hpp

  -------------------------------------------------------------------------

  responsible : IvanS

  special area: liveCache Simulator
  description : liveCache Sink implementation

  -------------------------------------------------------------------------





    ========== licence begin  GPL
    Copyright (c) 2002-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*****************************************************************************/


#ifndef LVCSIM_INTERNAL_HPP
#define LVCSIM_INTERNAL_HPP

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#define	LVCSIM_ONLY_GLOBALS
#include "LVCSimulator/LVCSim_Client.hpp"
#include "LVCSimulator/LVCSim_CheckpointIO.hpp"

#include "ggg00.h"
#include "ggg01.h"
#include "RunTime/Synchronisation/RTESync_Spinlock.hpp"
#include "geo573.h"

#undef global	// to prevent errors in iostream & company on Sun

#undef	NIL_OBJ_PAGE_NO	// to stop one warning
#include "liveCache/LVC_LibOmsInterface.hpp"

#ifdef  WIN32
#ifndef _DEBUG
#define	_DEBUG
#endif
#include <crtdbg.h>
#define LVCSIM_ASSERT(x) if (!x) _CrtDbgBreak();
#else
#include <assert.h>
#define LVCSIM_ASSERT(x) assert(x);
#endif


/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/




/*
 * Internal structures for liveCache simulator
 *
 */


#define	LVCSIM_CONTID_BITS		22		// #bits/container ID
#define	LVCSIM_OADDR_BITS		26		// #bits/object address within container


#ifndef	MAX_SCHEMA_NAME_LENGTH_CO10
#define MAX_SCHEMA_NAME_LENGTH_CO10	32
#endif

#ifndef	NULL
#define	NULL	0
#endif

#define MAX_CONCURRENT_TX       128     // max. # of concurrent transactions

#define	LVCSIM_THROW(txt)	throw DbpError(9999, txt)




// Wyde helper functions

/*!
	function: LVCSim_wstrcmp
	description: compares two Wyde strings
	arguments:
		s1 [in] pointer to first string
		s2 [in] pointer to second string
	returns: 0 if s1 == s2, -1 if s1 < s2, 1 if s1 > s2
*/
inline int LVCSim_wstrcmp(const OmsTypeWyde *s1, const OmsTypeWyde *s2)
{
	for (;;) {
		if (!*s1) {
			if (*s2) return -1;
			else return 0;
		}
		if (!*s2) return 1;
		if (*s1 < *s2) return -1;
		if (*s1 > *s2) return 1;
		++s1;
		++s2;
	}
}

/*!
	function: LVCSim_wstrcpy
	description: copies a Wyde string
	arguments:
		dest [in] pointer to destination
		src [in] pointer to source
	returns: pointer to destination
*/
inline OmsTypeWyde *LVCSim_wstrcpy(OmsTypeWyde *dest, const OmsTypeWyde *src)
{
	OmsTypeWyde *p = dest;
	while (*src) *p++ = *src++;
	*p = 0;
	return dest;
}



/*!
  Declaration: LVCSim_TID

  Description: This type is used internally to represent transaction timestamp.
 */

typedef	tsp00_Int4	LVCSim_TID;
#define	LVCSim_TID_NONE	-1
#define	LVCSim_TID_MAX	0x7fffffff

/*! enddeclaration: LVCSim_TID */


/*!
  Declaration: LVCSim_SID

  Description: This type is used internally to represent sink ID
 */

typedef	class LVCSim_liveCacheSink	*LVCSim_SID;

/*! enddeclaration: LVCSim_SID */


/*!
  Class: LVCSim_SchemaMeta

  Description: Schema metadata.
 */

class LVCSim_SchemaMeta {

protected:
	friend class	LVCSim_liveCacheSink;

	OmsTypeWyde		m_name[MAX_SCHEMA_NAME_LENGTH_CO10 + 1];
	int				m_id;
	int				m_next;
	

public:
	LVCSim_SchemaMeta(LVCSim_CheckpointReader &inp)
	{
		inp.read(&m_id, sizeof(m_id));
		inp.read(&m_next, sizeof(m_next));
		inp.read(&m_name[0], sizeof(m_name));
	}

	LVCSim_SchemaMeta(int _id, const OmsTypeWyde *_name) : m_id(_id), m_next(-1)
	{
		LVCSim_wstrcpy(m_name, _name);
	}

	void writeToStream(LVCSim_CheckpointWriter &o) const
	{
		o.write(&m_id, sizeof(m_id));
		o.write(&m_next, sizeof(m_next));
		o.write(&m_name[0], sizeof(m_name));
	}
};

/*! endclass: LVCSim_SchemaMeta */


class LVCSim_ContainerMeta {

protected:
    class DropInfo;

	friend class		LVCSim_liveCacheSink;
	friend class		LVCSim_ObjectHandle;
	friend class		KeyRangeIterator;

	size_t				m_size;					// object body size
	tgg00_FileId		m_containerDesc;		// container info
	tgg00_ObjColDesc	m_colDesc;				// column info

	class LVCSim_ObjectTree		*m_tree;			// key tree pointing to objects
	class LVCSim_OIDAllocator	*m_alloc;			// allocator for record heads

    static DropInfo             *m_firstDrop;       // first container to drop
    static DropInfo             *m_lastDrop;        // last container to drop
    static RTESync_Spinlock     m_dropLock;         // drop lock

	void *allocate(size_t sz);
	void deallocate(void *ptr);

public:
	LVCSim_ContainerMeta(LVCSim_CheckpointReader &i);
	LVCSim_ContainerMeta(int newID, size_t _size, tgg00_ObjColDesc *coldesc,
		const GUID *lpGUID);
	~LVCSim_ContainerMeta();

	inline int getContID() const
	{
		return m_containerDesc.fileObjFileNo_gg00();
	}

	void writeToStream(LVCSim_CheckpointWriter &o) const;

	class LVCSim_OIDAllocator *getAlloc() const
	{
		return m_alloc;
	}

    static void addDropped(                         // add to dropped container list
            class LVCSim_ContainerID &cid,
            LVCSim_TID tid,
            LVCSim_TID dropper,
            LVCSim_ContainerMeta *c);
    static void freeDropped(LVCSim_TID tid);        // free outdated containers up to tid
    static void freeAllDropped();                   // free all outdated containers
    static LVCSim_ContainerMeta *findDropped(       // find in dropped container list
        class LVCSim_ContainerID &cid, 
        LVCSim_TID tid);  
};


extern OMS_LibOmsInterface		*omsInterface;

#endif
