/* @lastChanged: "1998-06-24  10:45"
 *
 * @filename:    vcn81.cpp
 * @purpose:     "show info views"
 * @release:     7.1.0.0
 * @see:         "-.-"
 *
 * @copyright:   (c) 1998-2004 SAP AG"
 *
 * ==================================================================
 *
 * responsible:   Martin Reinecke (D024853 - Martin.Reinecke@SAP-AG.de)
 *                Bernd Vorsprach (D025588 - Bernd.Vorsprach@SAP-AG.de)
 *
 * created:       1998-12-04 by Martin Reinecke
 *
 * purpose:       show info views
 *
 * ==================================================================



    ========== licence begin  GPL
    Copyright (c) 1998-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




 */

/* ------------------------------------------------------------------
 * includes
 * ------------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "hcn80.h"
#include "hcn81.h"
#include "hcn90.h"

/* ------------------------------------------------------------------
 * PRIVATE PROTOTYPES
 * ------------------------------------------------------------------
 */
tcn00_Error cn81_InfoView(
      tin01_sql_session  * pSession,
      int                iView,
      char               * replyData,
      int                * replyLen,
      int                replyLenMax,
      bool               bDesc,
	    bool               bDataOnly,
      char               * szWhere);


/* ------------------------------------------------------------------
 * SPECIFICATION PRIVATE TYPES/MACROS
 * ------------------------------------------------------------------
 */
typedef struct InfoNameT {
    const char * szName;
    const char * szView;
    bool       bOneRowResult;
} InfoNameT;

static InfoNameT InfoNamesC[] = {
  {"INFOS"       , "INFO_INFOS"               , false },
  {"STATE"       , "INFO_STATE"               , true  },
  {"IO"          , "INFO_IO_STATISTICS"       , false }, 
  {"CACHES"      , "INFO_CACHE_STATISTICS"    , false }, 
  {"DEVSPACES"   , "INFO_DEVSPACES"           , false }, 
  {"BADDEVSPACES", "INFO_BAD_DEVSPACES"       , false }, 
  {"DATA"        , "INFO_DATADEV_STATE"       , true  }, 
  {"LOG"         , "INFO_LOG_STATE"           , true  }, 
  {"LOCKS"       , "INFO_LOCKS"               , true  }, 
  {"USERS"       , "INFO_CONNECTED_USERS"     , false }, 
  {"VERSIONS"    , "INFO_VERSIONS"            , true  },
  {"TABLES"      , "INFO_TABLES"              , false }, 
  {"COLUMNS"     , "INFO_COLUMNS"             , false },
  {"UPDSTAT"     , "INFO_UPDSTAT"             , false }, 
  {"UPDSTATW"    , "INFO_UPDSTAT_WANTED"      , false }, 
  {"INDEXES"     , "INFO_INDEXES"             , false }, 
  {"BADIDX"      , "INFO_BAD_INDEXES"         , false },
  {"UNUSEDIDX"   , "INFO_UNUSED_INDEXES"      , false },
  {"DISABLEDIDX" , "INFO_DISABLED_INDEXES"    , false },
  {"PARAMS"      , "INFO_PARAMETERS"          , false },
  {"EVENTS"      , "INFO_EVENTS"              , false },
  {"OMSCACHES"   , "INFO_OMS_CACHES"          , false },
  {"OMSMON"      , "INFO_OMS_MONITOR"         , false },
  {"CLSCON"      , "INFO_CLASSCONTAINERS"     , false },
  {"SYSDDSRVDB"  , "INFO_SYSDD_SERVERDBSTATE" , true  },
  {"SYSDDCONFIG" , "INFO_SYSDD_CONFIG"        , false },
  {"SYSDDMONITOR", "INFO_SYSDD_MONITOR"       , false }
};

#define INFO_STATE				1

//

#define INFO_DESC_OPT     "-d"
#define INFO_WHERE_OPT    "-w"

//

#define MAX_STATE_VALS     6

#define MAX_VALUES        MAX_STATE_VALS

//

/* PRIVATE FUNCTION cn81_RemoveDoublequotes
 * ------------------------------------------------------------------
 * purpose: remove doublequotes from a string
 *
 */
void cn81_RemoveDoublequotes(
      char * szValue)
{
  long nLength = 0;

  nLength = (long)strlen(szValue);

  if (nLength > 1) {
    if ((szValue[0]           == '"') &&
        (szValue[nLength - 1] == '"')    ) {
      strncpy(szValue, szValue+1, nLength-2);
      szValue[nLength-2] = '\0';
    } 
  }
} /* end cn81_RemoveDoublequotes */

/* PRIVATE FUNCTION cn81_InfoState
 * ------------------------------------------------------------------
 * purpose: show db state infos
 *
 */
/* ***
tcn00_Error cn81_InfoState(
      tin01_sql_session  * pSession,
      char               * replyData,
      int                * replyLen,
      int                replyLenMax,
      bool               bDesc)
{
  tcn00_Error	        nFuncReturn = OK_CN00;

  int                 rc;
  tsp00_C256c         errtext;

  char                szCommand[255];

  unsigned long       lPageSize         = 0;

  unsigned long       lUsedPermPages    = 0;
  unsigned long       lUsedTempPages    = 0;
  unsigned long       lLogPercent       = 0;     // Property
  unsigned long       lLogPages         = 0;     // Property
  unsigned long       lLogKB            = 0;     // Property
  unsigned long       lMaxLogPages      = 0;     // Property (22.04.1999)
  unsigned long       lMaxLogKB         = 0;     // Property (22.04.1999)
  
  unsigned long       lMaxPermPages     = 0;
  unsigned long       lReservedRedoSize = 0;
	
  unsigned long       lDataSize         = 0;	  	
  unsigned long       lTempPages        = 0;

  long	              lMaxDataPages     = 0;	 // Property (22.04.1999)
  unsigned long       lPermDataPages    = 0;     // Property
  unsigned long       lTempDataPages    = 0;     // Property
  unsigned long       lDataPages        = 0;     // Property

  unsigned long       lPermDataPercent  = 0;     // Property
  unsigned long       lTempDataPercent  = 0;     // Property
  unsigned long       lDataPercent;              // Property

  unsigned long       lMaxDataKB        = 0;     // Property (22.04.1999)
  unsigned long       lPermDataKB       = 0;     // Property
  unsigned long       lTempDataKB       = 0;     // Property
  unsigned long       lDataKB           = 0;     // Property
	
  unsigned long       lMaxUserTasks     = 0;     

  unsigned long       lSessions         = 0;     // Property
  unsigned long       lSessionsPercent  = 0;     // Property
  unsigned long       lSessionsMax      = 0;	 // Property (22.04.1999)

  unsigned long       lDataCache        = 0;     // Property
  unsigned long       lConverterCache   = 0;     // Property

  unsigned long       lBadDevspaces     = 0;     // Property (18.12.2000)

  unsigned long       lOMSDataCache     = 0;     // Property (05.09.2001)
  unsigned long       lOMSLogDataCache  = 0;     // Property (05.09.2001)

  tin01_c_hostvar     hostvar[MAX_VALUES];
  tin01_c_sqlca       sqlcaSelect;
  tin01_c_sqlca       sqlcaFetch;
  
  long                nIndex;

  char                * pCurrPos;

  char                szWhere[1];

  // 

  // PageSize

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "NUM(VALUE) ");
    strcat(szCommand, "FROM SYSDD.XPARAMETERS ");
    strcat(szCommand, "WHERE UPPER(DESCRIPTION) = '_PAGE_SIZE'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);
  
    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lPageSize);
    }

    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  

  //  values from serverdb_stat
  
  if (nFuncReturn == OK_CN00) {
    for (nIndex = 0; nIndex < MAX_STATE_VALS; nIndex++) {
      hostvar[nIndex].len = sizeof(unsigned long);
      hostvar[nIndex].c_type.becomes(cin01_c_ulong); 
    } 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "USED_PERM_PAGES, USED_TEMP_PAGES, ");
    strcat(szCommand, "LOG_PAGES, PCT_LOG_NOT_SAVED, LOG_NOT_SAVED, ");
//    strcat(szCommand, "MAX_PERM_PAGES, RESERVED_REDO_SIZE ");
    strcat(szCommand, "MAX_PERM_PAGES ");
    strcat(szCommand, "FROM SYSDD.SERVERDB_STATS");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = MAX_STATE_VALS;
      sqlcaFetch.paramCount  = MAX_STATE_VALS;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?, ?, ?, ?, ?, ?", 
                     &lUsedPermPages,
                     &lUsedTempPages,
                     &lMaxLogPages,
                     &lLogPercent,
                     &lLogPages,
                     &lMaxPermPages);
//                     &lReservedRedoSize);
    }
 
    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }

    lLogKB = lLogPages * (lPageSize / 1024);
	lMaxLogKB = lMaxLogPages * (lPageSize / 1024);

  }

  // DataSize

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "SUM(NUMERIC_VALUE) ");
    strcat(szCommand, "FROM SYSDD.CONFIGURATION ");
    strcat(szCommand, "WHERE UPPER(DESCRIPTION) LIKE 'DATA DEVSPACE *'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lDataSize);
    }

    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  
  
  //

  if (nFuncReturn == OK_CN00) {
    if (lReservedRedoSize == 0) {
      lTempPages = lDataSize - lMaxPermPages;
    } else {
      lTempPages = lReservedRedoSize;
    }

    if (lUsedTempPages > lTempPages) {
      lTempPages = lUsedTempPages;
    }

	lMaxDataPages = lDataSize;
    lPermDataPages = lUsedPermPages;                          
    lTempDataPages = lTempPages;
    lDataPages = lPermDataPages + lTempDataPages;

//    lPermDataPercent = (lDataSize > 0) ? lPermDataPages * 100 / lDataSize : 0;
//    lTempDataPercent = (lDataSize > 0) ? lTempDataPages * 100 / lDataSize : 0;
    lPermDataPercent = (lDataSize > 0) ? (unsigned long) (((float) lPermDataPages / (float) lDataSize) * 100) : 0;
    lTempDataPercent = (lDataSize > 0) ? (unsigned long) (((float) lTempDataPages / (float) lDataSize) * 100) : 0;

    lDataPercent = lPermDataPercent + lTempDataPercent;

    if (lDataPages > lDataSize) {
      lDataPages = lDataSize;
      lTempDataPercent = 100 - lPermDataPercent;
      lDataPercent = 100;
    }

	lMaxDataKB = lMaxDataPages * (lPageSize / 1024);
    lPermDataKB = lPermDataPages * (lPageSize / 1024);
    lTempDataKB = lTempDataPages * (lPageSize / 1024);
    lDataKB = lPermDataKB + lTempDataKB;
  }

  // Sessions

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "COUNT(SESSION) ");
    strcat(szCommand, "FROM SYSDD.TRANSACTIONS");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);
  
    if (rc == cin01_db_ok) {

      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lSessions);
    }

    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  

  // MaxUserTasks

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "NUM(VALUE) ");
    strcat(szCommand, "FROM SYSDD.XPARAMETERS ");
    strcat(szCommand, "WHERE UPPER(DESCRIPTION) = 'MAXUSERTASKS'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);
  
    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lMaxUserTasks);
    }

    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
    lSessionsPercent = (lMaxUserTasks > 0) ? (100 * lSessions) / lMaxUserTasks : 0;
	lSessionsMax = lMaxUserTasks;
  }  

  // DataCache

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "VALUE ");
    strcat(szCommand, "FROM SYSDD.MONITOR ");
    strcat(szCommand, "WHERE UPPER(TYPE) = 'CACHES' ");
    strcat(szCommand, "AND UPPER(DESCRIPTION) = 'DATA CACHE HIT RATE (%)'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lDataCache);
    }
  
    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  

  // ConverterCache

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "VALUE ");
    strcat(szCommand, "FROM SYSDD.MONITOR ");
    strcat(szCommand, "WHERE UPPER(TYPE) = 'CACHES' ");
    strcat(szCommand, "AND UPPER(DESCRIPTION) = 'CONVERTER CACHE HIT RATE (%)'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lConverterCache);
    }
  
    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  

  // Bad Devspaces

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "COUNT(DESCRIPTION) ");
    strcat(szCommand, "FROM SYSDD.SERVER_DB_STATE ");
    strcat(szCommand, "WHERE UPPER(DESCRIPTION) LIKE 'BAD DEV*'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);
  
    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lBadDevspaces);
    }

    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }

  }

  // OMSDataCache

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "VALUE ");
    strcat(szCommand, "FROM SYSDD.MONITOR ");
    strcat(szCommand, "WHERE UPPER(TYPE) = 'CACHES' ");
    strcat(szCommand, "AND UPPER(DESCRIPTION) = 'DATA CACHE OMS HIT RATE (%)'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lOMSDataCache);
    }
  
    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  

  // OMSLogDataCache

  if (nFuncReturn == OK_CN00) {
    hostvar[0].len = sizeof(unsigned long);
    hostvar[0].c_type.becomes(cin01_c_ulong); 

    SAPDB_strcpy(szCommand, "SELECT ");           
    strcat(szCommand, "VALUE ");
    strcat(szCommand, "FROM SYSDD.MONITOR ");
    strcat(szCommand, "WHERE UPPER(TYPE) = 'CACHES' ");
    strcat(szCommand, "AND UPPER(DESCRIPTION) = 'DATA CACHE OMS LOG HIT RATE (%)'");

    sqlcaSelect.inUse       = false;
    sqlcaSelect.varCount    = 0;
    sqlcaSelect.paramCount  = 0;
    sqlcaSelect.hostVar     = NULL;

    rc = i29sqlcmd(pSession, &sqlcaSelect, szCommand);

    if (rc == cin01_db_ok) {
      sqlcaFetch.inUse       = false;
      sqlcaFetch.varCount    = 1;
      sqlcaFetch.paramCount  = 1;
      sqlcaFetch.hostVar     = &hostvar[0];

      rc = i29sqlcmd(pSession, &sqlcaFetch, "FETCH NEXT INTO ?", &lOMSLogDataCache);
    }
  
    rc = (rc == DB_ERR_ROWNOTFOUND_CN00) ? 0 : rc;

    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    }
  
  }  
    
  //

  if (nFuncReturn == OK_CN00) {
    sprintf(replyData, "%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "END%s", LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    if (bDesc) {
      sprintf(pCurrPos, "SSNNNNNNNNNNNNNNNN%s", LINE_SEPSTRING_CN00);
      pCurrPos = replyData + strlen(replyData);
    }

    sprintf(pCurrPos, "Name                    | Value%s%s", LINE_SEPSTRING_CN00, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Data               (KB) = %lu%s",lDataKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Perm Data          (KB) = %lu%s",lPermDataKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Temp Data          (KB) = %lu%s",lTempDataKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Data            (Pages) = %lu%s",lDataPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Perm Data       (Pages) = %lu%s",lPermDataPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Temp Data       (Pages) = %lu%s",lTempDataPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Data                (%%) = %lu%s",lDataPercent, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Perm Data           (%%) = %lu%s",lPermDataPercent, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Temp Data           (%%) = %lu%s",lTempDataPercent, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    
    sprintf(pCurrPos, "Log                (KB) = %lu%s",lLogKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Log             (Pages) = %lu%s",lLogPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
	  sprintf(pCurrPos, "Log                 (%%) = %lu%s",lLogPercent, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Sessions                = %lu%s",lSessions, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Sessions            (%%) = %lu%s",lSessionsPercent, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Data Cache          (%%) = %lu%s",lDataCache, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Converter Cache     (%%) = %lu%s",lConverterCache, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    sprintf(pCurrPos, "Data Max           (KB) = %lu%s",lMaxDataKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Log Max            (KB) = %lu%s",lMaxLogKB, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Data Max        (Pages) = %lu%s",lMaxDataPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Log Max         (Pages) = %lu%s",lMaxLogPages, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Sessions Max            = %lu%s",lSessionsMax, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

  }

  //

  *replyLen = (int)strlen(replyData);

  // INFO_STATE View

  if (nFuncReturn == OK_CN00) {

    char *pData = replyData + *replyLen;	  	
    int  iLen = 0;

    szWhere[0] = '\0';

	  nFuncReturn = cn81_InfoView(pSession, INFO_STATE, pData, &iLen, replyLenMax, false, true, szWhere);

    *replyLen = (int)strlen(replyData);

  }

  // Bad Devspaces, OMSDataCache, OMSlogDataCache

  if (nFuncReturn == OK_CN00) {
    char *pData = replyData + *replyLen;	  	
    sprintf(pData,    "Bad Devspaces           = %d%s",lBadDevspaces, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    
    sprintf(pCurrPos, "Data Cache OMS      (%%) = %lu%s",lOMSDataCache, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
    sprintf(pCurrPos, "Data Cache OMS Log  (%%) = %lu%s",lOMSLogDataCache, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    *replyLen = (int)strlen(replyData);
  }

  return nFuncReturn;
} // cn81_InfoState

*** */

/* PRIVATE FUNCTION cn81_InfoView
 * ------------------------------------------------------------------
 * purpose: show info view
 *
 */
tcn00_Error cn81_InfoView(
      tin01_sql_session  * pSession,
      int                iView,
      char               * replyData,
      int                * replyLen,
      int                replyLenMax,
      bool               bDesc,
	    bool               bDataOnly,
      char               * szWhere)               
{
  tcn00_Error	        nFuncReturn = OK_CN00;
  char                szCommand[255];
  char              * pCurrPos;
  bool                bContinue = false;
  int                 rc;
  tsp00_C256c         errtext;
  
  //

  SAPDB_strcpy(szCommand, "SELECT * FROM ");           
  strcat(szCommand, InfoNamesC[iView].szView);
  if (szWhere[0] != '\0') {
    strcat(szCommand, " WHERE ");
    strcat(szCommand, szWhere);
  }

  pCurrPos = replyData;

  if (!bDataOnly) {
    sprintf(replyData, "%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
  }

  rc = i29selectnice(pSession, 
                     szCommand, 
                     pCurrPos, 
                     replyLenMax - (int)strlen(replyData),
                     InfoNamesC[iView].bOneRowResult,
                     bDesc,
					           bDataOnly,
                     bContinue);

  if (rc != 0) {
    nFuncReturn = ERR_SQL_CN00;
    i29errmsg(pSession, errtext);
    cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
  } else {
    if (bContinue) {
      // prepare next command 
      cn00DBMServerData::vcontrol()->szNextCommand.rawAssign("info_next");
      cn00DBMServerData::vcontrol()->nNextCommandSkip = 3;
    } // end if
  } // end if

  //

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* cn81_InfoView */

/* SPECIFICATION PUBLIC FUNCTIONS
 * ------------------------------------------------------------------
 */

/* PUBLIC FUNCTION cn81Info
 * ------------------------------------------------------------------
 * purpose: show info view
 *
 */
tcn00_Error cn81Info(
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax )
{
  tcn00_Error	         nFuncReturn = OK_CN00;
  
  tin01_sql_session  * pSession;
  tin01_sql_session    aSQLSession;
  bool                 bConnect    = false;

  char                 szName[255];
  char                 szParam[16];

  char               * pWhereOpt; 
  char                 szWhere[255];
  
  int                  nParam = 1;
  int                  iView; 
  bool                 bDesc = false;
  bool                 bMore = true; 
    
  /**/
  szWhere[0] = '\0';

  if (nFuncReturn == OK_CN00) {
    if (cn90GetToken(command->args, szName, nParam, 255)) {
      nParam++;
    } else {
      nFuncReturn = ERR_PARAM_CN00;
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    }
  }

  if (nFuncReturn == OK_CN00) {
    bMore = true;
    while (cn90GetToken(command->args, szParam, nParam, 16) && bMore)
    {
      nParam++;

      if (strcmp(szParam, INFO_DESC_OPT) == 0) {
        bDesc = true;
        bMore = false;
      } else {
        if (strcmp(szParam, INFO_WHERE_OPT) == 0) {

          pWhereOpt = (char *)strstr(command->args, INFO_WHERE_OPT);
          if (strlen(pWhereOpt) > (strlen(INFO_WHERE_OPT) + 1)) {
            pWhereOpt += (strlen(INFO_WHERE_OPT) + 1);
            SAPDB_strcpy(szWhere, pWhereOpt);
          }

          cn81_RemoveDoublequotes(szWhere);

          bMore = false;
        }
      }
    }
  }

  if (nFuncReturn == OK_CN00) {
    cn90Strip(szName);
    cn90StrUpperCopy(szName, szName, false);

    int   iCount = sizeof(InfoNamesC) / sizeof(InfoNameT);
    int   i = 0;
    bool  bFound = false;

    while ((i < iCount) && !bFound)    {
      if (strcmp(szName, InfoNamesC[i].szName) == 0) 
        bFound = true;
      i++;
    }

    if (bFound) {
      nFuncReturn = cn80SQLUserSession(vcontrol, replyData, replyLen, &pSession);
      if (nFuncReturn == ERR_NOSQLUSERSESSION_CN00) {
        pSession = &aSQLSession;
        nFuncReturn = cn80ConnectSQL ( vcontrol->dbname, pSession, replyData,replyLen);
        bConnect = (nFuncReturn == OK_CN00);
      } // end if

      if (nFuncReturn == OK_CN00) {
        iView = i - 1;
        nFuncReturn = cn81_InfoView(pSession, iView, replyData, replyLen, replyLenMax, bDesc, false, szWhere);
//        if (strcmp(szName, InfoNamesC[INFO_STATE].szName) == 0) {
//          nFuncReturn = cn81_InfoState(pSession, replyData, replyLen, replyLenMax, bDesc);
//        } else {
//          nFuncReturn = cn81_InfoView(pSession, iView, replyData, replyLen, replyLenMax, bDesc, false, szWhere);
//        }
      } // end if
    } else {
      nFuncReturn = ERR_PARAM_CN00;
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    }
  }

  if (bConnect) {
    // disconnect
    cn80ReleaseSQL(pSession);
    // delete next command 
    cn00DBMServerData::vcontrol()->szNextCommand.rawAssign("");
    cn00DBMServerData::vcontrol()->nNextCommandSkip = 0;
  } // end if

  //

  return nFuncReturn;
} /* cn81Info*/

/* PUBLIC FUNCTION cn81InfoNext
 * ------------------------------------------------------------------
 * purpose: show next part from info view
 *
 */
tcn00_Error cn81InfoNext(
      VControlDataT * vcontrol,
      CommandT      * command,
      char          * replyData,
      int           * replyLen,
      int             replyLenMax)
{
  tcn00_Error	         nFuncReturn = OK_CN00;
  tin01_sql_session  * pSession;
  char               * pCurrPos;
  bool                 bContinue = false;
  int                  rc;
  tsp00_C256c          errtext;
  
  /**/

  nFuncReturn = cn80SQLUserSession(vcontrol, replyData, replyLen, &pSession);
  
  if (nFuncReturn == OK_CN00) {

    sprintf(replyData, "%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);

    rc = i29fetchnice(pSession, 
                      pCurrPos, 
                      replyLenMax - (int)strlen(replyData),
                      bContinue);


    if (rc != 0) {
      nFuncReturn = ERR_SQL_CN00;
      i29errmsg(pSession, errtext);
      cn90AnswerSQLError(replyData, replyLen, nFuncReturn, (char *)errtext, rc);
    } else {
      if (bContinue) {
        // prepare next command 
        cn00DBMServerData::vcontrol()->szNextCommand.rawAssign("info_next");
        cn00DBMServerData::vcontrol()->nNextCommandSkip = 3;
      } // end if
    }
  }

  *replyLen = (int)strlen(replyData);

  //

  return nFuncReturn;
} /* cn81Info*/


