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

  module      : LVCSim_ObjectHandle.hpp

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

  responsible : IvanS

  special area: liveCache Simulator
  description : Internal object handle 

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





    ========== 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_OBJECTHANDLE_HPP
#define LVCSIM_OBJECTHANDLE_HPP

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

//#include "SAPDBCommon/SAPDB_Types.hpp"
#include "LVCSimulator/LVCSim_ObjectVerHandle.hpp"
#include "LVCSimulator/LVCSim_CheckpointIO.hpp"
#include "LVCSimulator/LVCSim_liveCacheSink.hpp"

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

/*!
 * \brief Object handle
 *
 * Defines the control block of a persistent object in memory.
 * This handle is allocated for each persistent object exactly once,
 * independent of how many past versions (before images) exist. OIDs
 * in simulator are actually logical pointers to objects of this type.
 */
class LVCSim_ObjectHandle : public LVCSim_OIDObject
{
public:
    /// Operation type, what has happened to the object in transaction.
    typedef enum {
        o_new,      ///< The object was created.
        o_update,   ///< The object was updated.
        o_delete    ///< The object was deleted.
    } OpType;

    /// Create a new object handle from checkpoint.
    LVCSim_ObjectHandle(LVCSim_CheckpointReader &r, size_t objsize);
    /// Create a new object handle.
    LVCSim_ObjectHandle(OmsTypeOid *oid, tgg91_PageRef *ref, LVCSim_SID tx)
        : m_lock(tx), m_lockChain(tx->m_lockChain),
          m_tid_max(LVCSim_TID_MAX), m_tid_min(tx->m_commitTime), m_tid_fmax(LVCSim_TID_MAX),
          m_node(NULL), m_versions(NULL)
    {
        getOid(oid);
        getRef(ref);
        tx->m_lockChain = this;
    }

    /// Destroy the object handle.
    ~LVCSim_ObjectHandle();

    /// Lookup visible object version.
    LVCSim_ObjectVerHandle *lookupObject(LVCSim_SID sid, int &histCount);

    /// Test for visibility.
    bool isVisible(LVCSim_SID sid);
    /// Test for visibility for changes.
    bool isVisibleForChange(LVCSim_SID sid);
    /// Test if this object's key can be reused.
    bool isNewable(LVCSim_SID sid);
    /// Test if object is a variable-sized continuation object
    bool isContObj(LVCSim_SID sid);

    /// Returns true, if the object is a keyed object
    inline bool isKeyedObj() const
    {
      return m_node != NULL;
    }

    /*!
     * \brief Get locked status.
     *
     * \return \c true, if the object is locked, \c false otherwise.
     */
    inline bool isLocked() const
    {
        return m_lock != NULL;
    }
    /// Try to exclusively lock this object.
    short lockObject(LVCSim_SID sid, size_t updateLen = 0, bool ignoreView = false);
    /// Unlock the object.
    short unlockObject(LVCSim_SID sid);

    /// Update the object.
    short update(LVCSim_SID sid, const void *data, size_t len, bool varsize, bool contObj);
    /// Logically delete the object.
    short remove(LVCSim_SID sid);

    /// Do commit/rollback for this item (low-level).
    void doEndTxLL(LVCSim_SID sid, bool commit, char operation);
    
    /// Operator new allocating the object in container.
    static void *operator new(size_t sz, LVCSim_ContainerMeta *cont);
    /// Operator delete deallocating the object in container.
    static void operator delete(void *ptr, LVCSim_ContainerMeta *cont);
    /// Operator new allocating the object in OID allocator.
    static void *operator new(size_t sz, LVCSim_OIDAllocator *alloc, unsigned int oid);
    /// Operator delete deallocating the object in OID allocator.
    static void operator delete(void *ptr, LVCSim_OIDAllocator *alloc, unsigned int oid);

    /// Destroy the object and associated information.
    void destroy(LVCSim_ContainerMeta *cont, LVCSim_SID sid);

    /// Dump the object to checkpoint writer stream.
    void writeToStream(LVCSim_CheckpointWriter &o, size_t objsize) const;


private:
    friend	class LVCSim_liveCacheSink;
    friend	class LVCSim_ObjectHandleObjLock;
    friend	class LVCSim_ObjectTree;
    friend	class LVCSim_ObjectTreeNode;

    /// Check if we have the object lock for given transaction.
	short checkLock(LVCSim_SID sid);
    /// Clear metadata before delete.
	void clear();
    /// Check, if already cleared.
    bool isCleared() const;

    /// Test for visibility.
    bool isVisibleNoLock(LVCSim_SID sid) const;
    /// Test for visibility for changes.
    short isVisibleForChangeNoLock(LVCSim_SID sid) const;
    /// Garbage collection.
    void GC(LVCSim_TID tid, LVCSim_SID sid,
        RTESync_Spinlock* &spinlock);


	LVCSim_SID				m_lock;		    ///< Sink ID of transaction that holds the lock on the object.
    LVCSim_ObjectHandle     *m_lockChain;   ///< Next object in lock chain.
	LVCSim_TID				m_tid_max;	    ///< Maximum TX time (to detect deleted).
	LVCSim_TID				m_tid_min;	    ///< Minimum TX time (to detect new).
	LVCSim_TID				m_tid_fmax;	    ///< Maximum TX time of the oldest version (optimization).

    /*!
     * \brief Containing object tree node, if any.
     *
     * This attribute contains a back-reference to the containing node in the tree.
     * It is stored here to provide faster iteration in key range iterators (to
     * prevent descending the tree anew for each increment).
     */
	class LVCSim_ObjectTreeNode	*m_node;	

    /*!
     * \brief Object version chain.
     *
     * Object version chain contains current and before images of the object.
     *
     * \see LVCSim_ObjectVerHandle for information about one object version.
     */
	LVCSim_ObjectVerHandle	*m_versions;
};


#endif
