/*!
  @file           RTEThread_ConsoleConnectionList.h
  @author         StefanP
  @special area   Kernel Console Thread
  @brief          Connection List
  @see            

\if EMIT_LICENCE
    ========== 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

\endif
*/



#ifndef RTETHREAD_CONSOLECONNECTIONLIST_H
#define RTETHREAD_CONSOLECONNECTIONLIST_H



/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/
# if defined (__cplusplus)
#include    "heo07.h"

#include    "RunTime/MemoryManagement/RTEMem_Allocator.hpp" 
#include    "RunTime/Threading/RTEThread_ConsoleWorkerBase.hpp"
#include    "SAPDBCommon/Tracing/SAPDBTrace_Topic.hpp"
#include    "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp"
#include    "RunTime/Threading/RTEThread_ConsoleRequest.h"


extern SAPDBTrace_Topic Console_Trace;

# endif /* __cplusplus */
/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/
# if defined (__cplusplus)
#define CONNECTION_LIST_ITEM_FREE       0
#define CONNECTION_LIST_ITEM_INVALID    SAPDB_MAX_UINT8

#define RTE_MAX_CONSOLE_CONNECTION      10     /* must be greater than zero */

# endif /* __cplusplus */

#define RTE_MAX_CONSOLE_IDLE_TIME      300    /* seconds; After this period of inactivity */
                                              /* time the connection is disconnected */

#define CONNECTION_SCAN_INTERVALL       15    /* seconds */

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/


/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/
# if defined (__cplusplus)

/*!
  @class          RTEThread_ConsoleConnectionListItem
   @description    List item (connection slot) of the connection list


                Instances of that class administer a console connection and hold all
                data necessary for that. This includes a pointer to a suitable
                worker instance (request processing, data communication).

 */


class RTEThread_ConsoleConnectionListItem 
{
public:
    
  /*!
     @description    Default constructor

   */


    RTEThread_ConsoleConnectionListItem ();

  /*!
     @description    Destructor

   */


    ~RTEThread_ConsoleConnectionListItem (); 

  /*!
     @description    Initialize the RTEThread_ConsoleConnectionListItem instance.
     @param          openData [in] - Reference to open data send by XCons 
                                       (-> Pipe -> Console Thread -> Command Queue -> Worker Thread)
     @param          connectionSlot [in] - Number of the connection slot
     @param          remoteRef [in] - Reference number of the remote side (XCons)
     @param          messageList [in/out] - Message list
     @return value   RTE_CONS_NO_ERROR:      No error
                RTE_CONS_ERROR:         Error: Connection has to be released
                RTE_CONS_FATAL_ERROR:   Connection slot is not free (Inconsistency) 
                                        -> Abort strongly recommended

   */
    

    SAPDB_UInt4     Initialize      (RTE_ConsoleOpenData const &    openData,
                                     SAPDB_UInt4 const              connectionSlot,
                                     SAPDB_UInt4 const              remoteRef,  
                                     SAPDBErr_MessageList &         messageList);

  /*!
     @description    Sets a connections slot as free.
     @param          pNextFree [in] - Pointer to the next free connection slot 
                                       in the connection list or NULL if there
                                       is no next free connection.
     @param          messageList [in/out] - Message list
     @return value   true
                false:  Connection slot is already free

   */

    
    SAPDB_Bool      SetFree         (RTEThread_ConsoleConnectionListItem * const    pNextFree,
                                     SAPDBErr_MessageList &                         messageList);
                    
  /*!
     @description    Get the unique connection handle of the connection
     @return value   Connection handle

   */
  

    RTE_ConsoleHandle   GetHandle   () const {return m_Handle;};

  /*!
     @description    Get the PID of the client (XCons)
     @return value   Client PID

   */
  

    RTE_PID         GetRemotePID    () const {return m_RemotePID;};

  /*!
     @description    Get the worker instance
     @return value   Pointer to worker instance

   */

    
    inline  RTEThread_ConsoleWorkerBase *   GetWorker () const;

  /*!
     @description    If the connection slot is free it gets a pointer to the next free slot
     @param          ppNext [out] - pointer to the next free connection slot
                                        if this connection slot is free. Otherwise: NULL
     @return value   true:   *ppNext holds the next free connection slot
                false:  This Connection is not free

   */
  

    inline  SAPDB_Bool  GetNextFreeConnectListItem (RTEThread_ConsoleConnectionListItem **   ppNext) const;

  /*!
     @description    Set the pointer to the next free list item
     @param          pNext [in] - pointer to the next free list item
     @return value   none

   */
  

    inline  void        SetNextFreeConnectListItem (RTEThread_ConsoleConnectionListItem * const   pNext);


  /*!
     @description    Lock the connection slot

   */
  

    inline  void        Lock        ();

  /*!
     @description    Unlock the connection slot

   */
  

    inline  void        Unlock      ();

private:

    RTE_ConsoleHandle   m_Handle;
    RTE_PID             m_RemotePID;
    teo07_Mutex         m_ConnectionListItemMutex;

    union
    {
        RTEThread_ConsoleConnectionListItem *   pFreeItem;
        RTEThread_ConsoleWorkerBase         *   pWorker;
    }   m_Next;
};



inline  RTEThread_ConsoleWorkerBase    *RTEThread_ConsoleConnectionListItem::GetWorker () const 
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionListItem::GetWorker", 
                             Console_Trace, 9);
    if (CONNECTION_LIST_ITEM_FREE == m_Handle)
    {
        return NULL;
    }
    else
    {
        return m_Next.pWorker;
    }

}

/*---------------------------------------------------------------------------*/

inline  SAPDB_Bool  RTEThread_ConsoleConnectionListItem::GetNextFreeConnectListItem 
(
    RTEThread_ConsoleConnectionListItem    **   ppNext
) 
const 
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionListItem::GetNextFreeConnectListItem", 
                             Console_Trace, 9);
    if (CONNECTION_LIST_ITEM_FREE != m_Handle)
    {
        *ppNext = NULL;
        return false;
    }
    else
    {
        *ppNext = m_Next.pFreeItem;
        return true;
    }
}

/*---------------------------------------------------------------------------*/

inline  void    RTEThread_ConsoleConnectionListItem::SetNextFreeConnectListItem 
(
    RTEThread_ConsoleConnectionListItem * const   pNext
) 
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionListItem::SetNextFreeConnectListItem", 
                             Console_Trace, 9);
    m_Next.pFreeItem = pNext;
}

/*---------------------------------------------------------------------------*/

inline  void    RTEThread_ConsoleConnectionListItem::Lock (void)
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionListItem::Lock", 
                             Console_Trace, 9);
    sqlbeginmutex(&m_ConnectionListItemMutex);
}

/*---------------------------------------------------------------------------*/

inline  void    RTEThread_ConsoleConnectionListItem::Unlock (void)
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionListItem::Unlock", 
                             Console_Trace, 9);
    sqlendmutex(&m_ConnectionListItemMutex);
}



/*!
  @class          RTEThread_ConsoleConnectionList
   @description    Connection list (Singleton)


                Implements a connection list of RTEThread_ConsoleConnectionListItem's

 */


class RTEThread_ConsoleConnectionList 
{
public:

  /*!
     @description    Return reference to single instance of RTEThread_ConsoleConnectionList
     @return value   Reference to RTEThread_ConsoleCommandQueue instance

   */


    static  RTEThread_ConsoleConnectionList    &   Instance ();

  /*!
     @brief          Destructor

   */


    ~RTEThread_ConsoleConnectionList    ();

  /*!
     @description    If the connection slot is free it gets a pointer to the next free slot
     @param     openMode [in]           - RTE_OPEN_EXISTING    : Open existing connection 
                                          RTE_CREATE_NEW       : Open new connection
     @param     requestData [in]        - Reference to request send by XCons 
                                          (-> Pipe -> Console Thread -> Command Queue -> Worker Thread)
     @param     index [in]              - Index of the current worker thread
     @param     ppConnectionItem[out]   - Pointer to the opened connection slot if successful 
                                          (see below: RTE_CONS_NO_ERROR)
     @param     messageList [in/out]    - Message list

     @return     RTE_CONS_NO_ERROR:      Connection was opend successfully


                  openMode == RTE_OPEN_EXISTING:
                  RTE_CONS_ERROR:         Connection does not exist anymore
                  openMode == RTE_CREATE_NEW:
                  RTE_CONS_ERROR:         Open failed but the connection list is still consistent
                                          -> No reason for termination
                  RTE_CONS_FATAL_ERROR:   Inconsistency 
                                          -> Abort should be performed

   */

    
    SAPDB_UInt4     OpenConnection      (SAPDB_UInt4 const                              openMode,
                                         RTEThread_ConsoleRequest const &               requestData,
                                         SAPDB_UInt4 const                              index,
                                         RTEThread_ConsoleConnectionListItem **         ppConnectionItem,
                                         SAPDBErr_MessageList &                         messageList);

  /*!
     @description    Set the pointer to the next free list item
     @param          pConnectionItem [in] - pointer to the connection slot to be freed
     @param          remoteRef [in] - reference of the remote side (XCons)
     @param          messageList [in/out] - Message list
     @return value   true:   Release succeeded
                false:  Release failed

   */
  

    SAPDB_Bool      ReleaseConnection   (RTEThread_ConsoleConnectionListItem * const    pConnectionItem,
                                         SAPDB_UInt4 const                              remoteRef,
                                         SAPDBErr_MessageList &                         messageList);


  /*!
     @description    Determine existing connections which were not used for a special period
                of time (MAX_CONSOLE_IDLE_TIME). Those connection are released.

   */
  

    void            ScanConnectionsForTimeout    ();


  /*!
     @brief          

   */


    SAPDB_UInt4    GetNumConnections    () const    {return (m_NumConnections);}

  /*!
     @brief          

   */

    SAPDB_UInt8    IncrementConnectionCounter ()    {return (++m_ConnectionCounter);}  

  /*!
     @description    Lock the connection list

   */
  

    inline  void        Lock        ();

  /*!
     @description    Unlock the connection list

   */
  

    inline  void        Unlock      ();

private:
/*!
   @brief          Constructor


   The default constructor is privat to this class to avoid instantiation outside of the class.

 */


    RTEThread_ConsoleConnectionList ();

/*!
   @brief          Instance of RTEThread_ConsoleCommandQueue
   @return value   Reference to RTEThread_ConsoleCommandQueue instance.


   Get reference to single instance of RTEThread_ConsoleCommandQueue.

 */

    SAPDB_Bool Initialize (SAPDBErr_MessageList        &   messageList);




    static  RTEThread_ConsoleConnectionList        *m_Instance;
            SAPDB_UInt8                             m_ConnectionCounter;
            RTEThread_ConsoleConnectionListItem    *m_ConnectionList;
            RTEThread_ConsoleConnectionListItem    *m_FreeList;
            SAPDB_UInt4                             m_NumConnections;
            teo07_Mutex                             m_ConnectionListMutex;
};



/*---------------------------------------------------------------------------*/

inline  void    RTEThread_ConsoleConnectionList::Lock (void)
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionList::Lock", 
                             Console_Trace, 9);
    sqlbeginmutex(&m_ConnectionListMutex);
}

/*---------------------------------------------------------------------------*/

inline  void    RTEThread_ConsoleConnectionList::Unlock (void)
{
    SAPDBTRACE_METHOD_DEBUG ("RTEThread_ConsoleConnectionList::Unlock", 
                             Console_Trace, 9);
    sqlendmutex(&m_ConnectionListMutex);
}

# endif /* __cplusplus */

/*! @name extern "C" Functions */
 /*@{*/
/* for function descritpions refer to class RTEThread_ConsoleConnectionList
*/

/*!
   @description    refer RTEThread_ConsoleConnectionList::ScanConnectionsForTimeout

 */
 

externC void   RTEThread_ConsoleScanConnectionsForTimeout ();

/*@}*/

#endif  /* RTETHREAD_CONSOLECONNECTIONLIST_H */
