/*!
  @file           RTE_Installation.hpp
  @author         JoergM, RobinW
  @brief          DBM Support: SAPDB Instance and Database Registration and Management Interfaces
  @see            

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2001-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 RTE_INSTALLATION_HPP
#define RTE_INSTALLATION_HPP

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

#include "RunTime/RTE_Types.h"
#include "RunTime/MemoryManagement/RTEMem_Allocator.hpp"
#include "Container/Container_List.hpp"
#include "RunTime/RTE_SpeedInfo.hpp"
#include "SAPDBCommon/SAPDB_sprintf.h"

#ifdef _WIN32
#include "gos44.h"      /* nocheck */
#else
#include <unistd.h>     /* nocheck */
#include <sys/stat.h>   /* nocheck */
#endif
/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

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

/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/
class RTE_Database;
class PidList;

#ifndef _WIN32

class RTE_FuserAccess   /*!<_*/
{
private:
    enum fuserState
    {
        notChecked,
        inPath,
        inUsrSbin,
        inSbin,
        noAccess
    }
    ;

    static fuserState GetAccess(void);

    static void CheckFuserExistence(void);

    static fuserState m_fuserState;
friend class RTE_Installation;
};
#endif

/*!
  RTE_DBKey
  the unique key of a database software installation
*/
typedef SAPDB_Char RTE_DBKey[256];

/*!
  @class RTE_Installation
  @brief installation information class

  class containing information about one database software installation: version, root path, enumeration of installed databases
*/
class RTE_Installation
{
public:

    /*!
      @struct InstVersionInfo
      @brief version of a database software installation
    */
    struct InstVersionInfo
    {
        RTE_DBKey   key;
        SAPDB_Byte  release;
        SAPDB_Byte  major;
        SAPDB_Byte  minor;
        SAPDB_Byte  build;
    };

    /*!
      Function: GetDBRoot
      Description: Return current dbroot
      Return value: Reference to dbroot of installation
     */
    const RTE_Path & GetDBRoot() const { return m_dbRoot; }

    /*!
      Function: GetVersion
      Description: Return installation version
      Return value: 
     */
    const InstVersionInfo & GetVersion() const { return m_Version; }

    /*!
      Function: GetSpeeds
      Description:Get a list of all available speeds
      Return value:
     */
    RTE_SpeedList& GetSpeedList()
    {
        return m_speedList;
    };

    /*!
      Function: GetDatabases
      Description: Get a container of registered databases
      
      This container allows to iterate all registered databases for this
      installation.
      Arguments: errList [out] Filled with message in case of trouble
      Return value: The database list (may be empty)
     */
    Container_List<RTE_Database>* GetDatabases(SAPDBErr_MessageList &errList);

    RTE_Installation(const RTE_Installation &templateInst)
        :
        m_speedList(RTEMem_Allocator::Instance()),
#ifndef _WIN32
        m_fuserState(templateInst.m_fuserState),
#endif
        m_Version(templateInst.m_Version)
    {
        strncpy(m_dbRoot,templateInst.m_dbRoot,sizeof(RTE_Path));
        m_speedList.Initialize(templateInst.m_speedList);
    };
    ~RTE_Installation()
    {
        ;
    };

protected:
    RTE_Installation(RTE_Path &dbRoot, InstVersionInfo &version):
#ifndef _WIN32
         m_fuserHasBeenCalled(false),
#ifdef LINUX    // PTS 1137490: use /proc/ file system entries rather than fuser on linux, because fuser calls are expensive
         m_fuserState(RTE_FuserAccess::noAccess),
#else
         m_fuserState(RTE_FuserAccess::GetAccess()),
#endif
#endif
        m_speedList(RTEMem_Allocator::Instance())
    {
        strncpy(m_dbRoot,dbRoot,sizeof(RTE_Path));
        m_Version = version;

        AddSpeed(speedFast);
        AddSpeed(speedQuick);
        AddSpeed(speedSlow);

        if((version.release == 7 && version.major >= 5  )   // http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1124053
            ||(version.release == 7 && version.major == 4 && version.minor >= 2 )
            ||(version.release == 7 && version.major == 2 && version.minor == 5 && version.build >= 16)
            ||(version.release == 7 && version.major == 2 && version.minor >= 5 ))
        {
            AddSpeed(speedTest);
        }
    }

    RTE_SpeedList   m_speedList;

private:
    RTE_Path        m_dbRoot;
    InstVersionInfo m_Version;
    friend class RTE_DBRegister;

    SAPDB_Bool dbHasExecutable (
        const SAPDB_Char *kernelName )
    {
        RTE_Path fullKernelPath;  // PTS 1105631
        SAPDB_Int		    	rc = 0;
#ifdef _WIN32
        SAPDB_sprintf ( fullKernelPath, sizeof(RTE_Path), "%s\\%s", m_dbRoot, kernelName ) ;

        SAPDB_UInt                 ulTmp       = 0;
        SAPDB_Int                  lAtt        = 0;
        rc = sql44c_get_file_info ( fullKernelPath, &lAtt, &ulTmp, &ulTmp );
#else
        SAPDB_sprintf ( fullKernelPath, sizeof(RTE_Path), "%s/pgm/%s", m_dbRoot, kernelName);
        struct stat		statInfo;

        rc = stat ((SAPDB_Char *)fullKernelPath, &statInfo);
#endif
        return (rc == 0);
    }

    void AddSpeed(RTE_SpeedInfo &speed)
    {
        RTE_SpeedInfo newSpeed(speed);
        if(!dbHasExecutable(speed.ExecutableName()))
        {
            newSpeed.SetExists(false);
        }
        m_speedList.InsertEnd(newSpeed);
    }

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


#ifndef _WIN32
    SAPDB_Bool dbHasSpecificProcess (
        SAPDB_Char *dbname,
        const SAPDB_Char *kernelpgm);

    void FillPidList(const SAPDB_Char *pExecutableName,PidList &pidList);

    SAPDB_Bool dbHasRunningProcess ( RTE_DBName &dbname,RTE_SpeedInfo speed );

    SAPDB_Bool MatchInProcFS(RTE_DBName &dbname,RTE_SpeedInfo speed,tsp00_TaskId pid);

    RTE_FuserAccess::fuserState m_fuserState;

    PidList *m_pPidList;

    SAPDB_Bool m_fuserHasBeenCalled;
#endif
};

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/

#endif
