blob: 305ce75e6ccfaa44fa79a76c343698360a00c34e [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
#ifndef HSLOG_H
#define HSLOG_H
/* -*-C++-*-
*****************************************************************************
*
* File: hs_log.h
* Description: Logging utilities
* Created: 03/25/96
* Language: C++
*
*
*
*
*****************************************************************************
*/
#include <stdio.h>
#include <fstream>
#include "hs_const.h"
#include <time.h> // for getimeofday
#include "ComSysUtils.h" // for NA_gettimeofday
// Merge diags area.
void HSFuncMergeDiags( Lng32 sqlcode
, const char *string0 = NULL
, const char *string1 = NULL
, NABoolean needCLIDiags = FALSE
, Lng32 fsError = 0
);
// -----------------------------------------------------------------------
// Class to catch and summarize diagnostic info at procedure return.
//
// Example:
// long retcode;
// HSErrorCatcher ec( retcode
// , sqlcode
// , NULL
// , TRUE
// );
// retcode = somefunc(...);
// if (retcode)
// return retcode;
// retcode = somefunc2(...);
// if (retcode)
// return retcode;
// -----------------------------------------------------------------------
class HSErrorCatcher {
public:
HSErrorCatcher( Lng32 &retcode
, short sqlcode
, const char *msg
, Int32 needCLIDiags
, NABoolean inactivate=FALSE
)
: retcode_(retcode),
sqlcode_(sqlcode),
string0_(msg),
needCLIDiags_(needCLIDiags),
string1_(NULL),
isFinalized_(FALSE),
inactivated_(inactivate)
{
retcode_ = 0;
}
~HSErrorCatcher()
{
finalize();
}
inline void setString1(const char *str)
{
string1_ = str;
}
// This function is used to write an error to the diagnostics area if one
// occurred. It is typically called by the destructor when a stack-allocated
// HSErrorCatcher goes out of scope, but may be called directly. If so, it
// becomes a no-op for any subsequent calls, including the one by the dtor.
//
void finalize()
{
// Add error to diagnostic area if not EOF or float primary key (-1120).
if ( !isFinalized_ &&
!inactivated_ &&
retcode_ &&
retcode_ != HS_EOF &&
retcode_ != -HS_PKEY_FLOAT_ERROR &&
sqlcode_ )
HSFuncMergeDiags(sqlcode_, string0_, string1_, needCLIDiags_);
isFinalized_ = TRUE;
}
private:
Lng32 &retcode_; // TRUE if error occurs.
short sqlcode_; // error (<0) or warning (>0).
const char *string0_; // optional string0.
NABoolean needCLIDiags_; // TRUE if need to retrieve additional diags
// from CLI.
const char *string1_; // optional string1.
NABoolean isFinalized_; // becomes true if error caught before object destroyed
// (prevents action by dtor)
NABoolean inactivated_; // Set to TRUE if we want to suppress the action
// of finalize() in the destructor. We might do
// this because this HSErrorCatcher was created
// within the scope of another; if we don't suppress
// we will report the same error twice. Another
// reason for doing this is we might be in a retry
// loop and don't want to report diagnostics for
// failures we will retry. (In this latter case,
// there typically will be another HSErrorCatcher
// above the retry loop.
};
// -----------------------------------------------------------------------
// Standalone functions.
// -----------------------------------------------------------------------
// Log the location of the error.
void HSFuncLogError(Lng32 error, char *filename, Lng32 lineno);
// Wrapper to handle assertion failure. Do not assert a condition with any
// side effects, as it is evaluated a second time if false.
#define HS_ASSERT(b) \
{ \
if (NOT (b)) \
{ \
GetHSContext()->preAssertionFailure("" # b "", __FILE__, __LINE__); \
CMPASSERT(b); \
} \
}
//Ignore the following WARNINGS
// [6008] missing single-column histograms
// [6007] missing multi-column histograms
// [4030] non-standard DATETIME format
// [2053] Optimizer pass two assertion failure (optimizer still attempts to produce a plan)
// [4] internal Warning
#define HSFilterWarning(retcode) \
{ \
if ((retcode == 6008) || \
(retcode == 6007) || \
(retcode == 4030) || \
(retcode == 2053) || \
(retcode == HS_WARNING)) \
retcode = 0; \
}
// Map any error (<0) code other than HS_PKEY_FLOAT_ERROR to -1.
#define HSFilterError(retcode) \
{ \
if (retcode < 0 && retcode != -HS_PKEY_FLOAT_ERROR) retcode = -1; \
}
#define HSHandleErrorIUS(retcode) \
{ \
HSFilterWarning(retcode); \
if (retcode) { \
end_IUS_work(); \
} \
HSHandleError(retcode); \
}
#define HSHandleError(retcode) \
{ \
HSFilterWarning(retcode); \
if (retcode) { \
HSFuncLogError(retcode, (char *)HS_FILE, (Lng32)__LINE__); \
HSFilterError(retcode); \
return retcode; \
} \
}
#define HSLogError(retcode) \
{ \
HSFilterWarning(retcode); \
if (retcode) { \
HSFuncLogError(retcode, (char *)HS_FILE, (Lng32)__LINE__); \
} \
}
#define HSExitIfError(retcode) \
{ \
HSFilterWarning(retcode); \
if (retcode) { \
HSFuncLogError(retcode, (char *)HS_FILE, (Lng32)__LINE__); \
HSFilterError(retcode); \
HSClearCLIDiagnostics(); \
return retcode; \
} \
}
// -----------------------------------------------------------------------
// CLASS: HSLogMan Log Manager
// -----------------------------------------------------------------------
const Lng32 MAX_TIMING_EVENTS = 10; //3; //@ZXtemp 10;
class HSLogMan
{
public:
static HSLogMan* Instance();
inline NABoolean LogNeeded() const {return logNeeded_;}
void Log(const char *data); /* data string to write to log */
void StartLog(NABoolean needExplain = TRUE, /* start the log */
const char* logFileName = NULL); /* allow override of default */
void StopLog(); /* stop the log */
void ClearLog(); /* erase the log file */
void StartTimer(const char *title = ""); /* start time-watch */
void StopTimer(); /* stop time-watch */
void LogTimeDiff(const char *text = "", NABoolean reset = FALSE); /* log time difference */
void LogTimestamp(const char *text = ""); /* log current local time, to microseconds */
char msg[2000]; /* general purpose buffer for */
/* formmatting messages */
NAString* logFileName() { return logFile_; };
NABoolean ContainDirExist(const char* path);
NABoolean GetLogFile(NAString & logFile, const char* cqc_value);
protected:
HSLogMan(); /* ensure only 1 instance of class */
private:
NABoolean logNeeded_; /* T: logging is needed */
NAString *logFile_; /* log filename */
Lng32 currentTimingEvent_;
Int64 startTime_[MAX_TIMING_EVENTS];
NABoolean explainOn_;
timeval prevTime_;
char title_[MAX_TIMING_EVENTS][1000];
static THREAD_P HSLogMan* instance_; /* 1 and only 1 instance */
};
#endif /* HSLOG_H */