Commit 32cd5acd authored by joreland@mysql.com's avatar joreland@mysql.com

wl1668 -

Add support for getting events via mgmapi
removed all traces of stat port
parent 27a4e6e2
......@@ -24,6 +24,65 @@
#include <kernel/LogLevel.hpp>
#include <signaldata/EventReport.hpp>
class EventLoggerBase {
public:
virtual ~EventLoggerBase();
/**
* LogLevel settings
*/
LogLevel m_logLevel;
/**
* Find a category matching the string
*
* @param str string to match.
* @param cat the event category.
* @param exactMatch only do exact matching.
*
* @return TRUE if match is found, then cat is modified
* FALSE if match is not found
*/
static bool matchEventCategory(const char * str,
LogLevel::EventCategory * cat,
bool exactMatch = false);
/**
* Returns category name or NULL if not found.
*
* @param cat the event category.
* @return category name.
*/
static const char * getEventCategoryName(LogLevel::EventCategory cat);
/**
* Specifies allowed event categories/log levels.
*/
struct EventCategoryName {
LogLevel::EventCategory category;
const char * name;
};
static const EventCategoryName eventCategoryNames[];
static const Uint32 noOfEventCategoryNames;
/**
* This matrix defines which event should be printed when
*
* threshold - is in range [0-15]
* severity - DEBUG to ALERT (Type of log message)
*/
struct EventRepLogLevelMatrix {
EventReport::EventType eventType;
LogLevel::EventCategory eventCategory;
Uint32 threshold;
Logger::LoggerLevel severity;
};
static const EventRepLogLevelMatrix matrix[];
static const Uint32 matrixSize;
};
/**
* The EventLogger is primarily used for logging NDB events
* in the Management Server. It inherits all logging functionality of Logger.
......@@ -58,7 +117,7 @@
* @see Logger
* @version #@ $Id: EventLogger.hpp,v 1.3 2003/09/01 10:15:52 innpeno Exp $
*/
class EventLogger : public Logger
class EventLogger : public EventLoggerBase, public Logger
{
public:
/**
......@@ -70,7 +129,7 @@ public:
/**
* Destructor.
*/
~EventLogger();
virtual ~EventLogger();
/**
* Opens/creates the eventlog with the specified filename.
......@@ -92,16 +151,6 @@ public:
*/
void close();
/**
* Logs the NDB event.
*
* @param nodeId the node id of event origin.
* @param eventType the type of event.
* @param theData the event data.
* @deprecated use log(int eventType, const Uint32* theData, NodeId nodeId)
*/
void log(NodeId nodeId, int eventType, const Uint32* theData);
/**
* Logs the NDB event.
*
......@@ -109,16 +158,19 @@ public:
* @param theData the event data.
* @param nodeId the node id of event origin.
*/
void log(int eventType, const Uint32* theData, NodeId nodeId = 0);
virtual void log(int eventType, const Uint32* theData, NodeId nodeId = 0);
/**
* Returns the current log levels.
* Enable, disable log levels to filter the events that are sent to the
* eventlog.
* Returns the event text for the specified event report type.
*
* @return the log level.
* @param type the event type.
* @param theData the event data.
* @param nodeId a node id.
* @return the event report text.
*/
LogLevel& getLoglevel();
static const char* getText(char * dst, size_t dst_len,
int type,
const Uint32* theData, NodeId nodeId = 0);
/**
* Returns the log level that is used to filter an event. The event will not
......@@ -127,6 +179,7 @@ public:
* @return the log level filter that is used for all event categories.
*/
int getFilterLevel() const;
/**
* Sets log level filter. The event will be logged if
* the event category's log level is <= 'filterLevel'.
......@@ -135,92 +188,16 @@ public:
*/
void setFilterLevel(int filterLevel);
/**
* Returns the event text for the specified event report type.
*
* @param type the event type.
* @param theData the event data.
* @param nodeId a node id.
* @return the event report text.
*/
static const char* getText(int type,
const Uint32* theData, NodeId nodeId = 0);
/**
* Find a category matching the string
*
* @param str string to match.
* @param cat the event category.
* @param exactMatch only do exact matching.
*
* @return TRUE if match is found, then cat is modified
* FALSE if match is not found
*/
static bool matchEventCategory(const char * str,
LogLevel::EventCategory * cat,
bool exactMatch = false);
/**
* Returns category name or NULL if not found.
*
* @param cat the event category.
* @return category name.
*/
static const char * getEventCategoryName(LogLevel::EventCategory cat);
/**
* Specifies allowed event categories/log levels.
*/
struct EventCategoryName {
LogLevel::EventCategory category;
const char * name;
};
static const EventCategoryName eventCategoryNames[];
static const Uint32 noOfEventCategoryNames;
/**
* This matrix defines which event should be printed when
*
* threshold - is in range [0-15]
* severity - DEBUG to ALERT (Type of log message)
*/
struct EventRepLogLevelMatrix {
EventReport::EventType eventType;
LogLevel::EventCategory eventCategory;
Uint32 threshold;
Logger::LoggerLevel severity;
};
static const EventRepLogLevelMatrix matrix[];
/**
* Default log levels for management nodes.
*
* threshold - is in range [0-15]
*/
struct EventLogMatrix {
LogLevel::EventCategory eventCategory;
Uint32 threshold;
};
static const EventLogMatrix defEventLogMatrix[];
static const Uint32 matrixSize;
static const Uint32 defEventLogMatrixSize;
private:
/** Prohibit */
EventLogger(const EventLogger&);
EventLogger operator = (const EventLogger&);
bool operator == (const EventLogger&);
LogLevel m_logLevel;
Uint32 m_filterLevel;
STATIC_CONST(MAX_TEXT_LENGTH = 256);
static char m_text[MAX_TEXT_LENGTH];
char m_text[MAX_TEXT_LENGTH];
};
......
......@@ -130,18 +130,25 @@ public:
*/
Uint32 getLogLevel(EventCategory ec) const;
/**
* Set this= max(this, ll) per category
*/
LogLevel& set_max(const LogLevel& ll);
bool operator==(const LogLevel& l) const {
return memcmp(this, &l, sizeof(* this)) == 0;
}
private:
/**
* The actual data
*/
Uint32 logLevelData[LOGLEVEL_CATEGORIES];
LogLevel(const LogLevel &);
Uint8 logLevelData[LOGLEVEL_CATEGORIES];
};
inline
LogLevel::LogLevel(){
clear();
clear();
}
inline
......@@ -176,5 +183,14 @@ LogLevel::getLogLevel(EventCategory ec) const{
return logLevelData[ec];
}
inline
LogLevel &
LogLevel::set_max(const LogLevel & org){
for(Uint32 i = 0; i<LOGLEVEL_CATEGORIES; i++){
if(logLevelData[i] < org.logLevelData[i])
logLevelData[i] = org.logLevelData[i];
}
return * this;
}
#endif
......@@ -27,7 +27,7 @@
* RECIVER: SimBlockCMCtrBlck
*/
class EventSubscribeReq {
struct EventSubscribeReq {
/**
* Receiver(s)
*/
......@@ -38,9 +38,8 @@ class EventSubscribeReq {
*/
friend class MgmtSrvr;
public:
STATIC_CONST( SignalLength = 22 );
private:
/**
* Note: If you use the same blockRef as you have used earlier,
* you update your ongoing subscription
......@@ -55,6 +54,15 @@ private:
Uint32 theCategories[10];
Uint32 theLevels[10];
EventSubscribeReq& operator= (const LogLevel& ll){
noOfEntries = _LOGLEVEL_CATEGORIES;
for(size_t i = 0; i<noOfEntries; i++){
theCategories[i] = i;
theLevels[i] = ll.getLogLevel((LogLevel::EventCategory)i);
}
return * this;
}
};
#endif
......@@ -18,6 +18,7 @@
#define SET_LOGLEVEL_ORD_HPP
#include <LogLevel.hpp>
#include "EventSubscribeReq.hpp"
#include "SignalData.hpp"
/**
......@@ -51,6 +52,24 @@ private:
* Note level is valid as 0-15
*/
void setLogLevel(LogLevel::EventCategory ec, int level = 7);
SetLogLevelOrd& operator= (const LogLevel& ll){
noOfEntries = _LOGLEVEL_CATEGORIES;
for(size_t i = 0; i<noOfEntries; i++){
theCategories[i] = i;
theLevels[i] = ll.getLogLevel((LogLevel::EventCategory)i);
}
return * this;
}
SetLogLevelOrd& operator= (const EventSubscribeReq& ll){
noOfEntries = ll.noOfEntries;
for(size_t i = 0; i<noOfEntries; i++){
theCategories[i] = ll.theCategories[i];
theLevels[i] = ll.theLevels[i];
}
return * this;
}
};
inline
......
......@@ -55,24 +55,6 @@
extern "C" {
#endif
/**
* Format of statistical information from the NDB Cluster.
* STATISTIC_LINE is sent on the statistical port from the Management server,
* each line is timestamped with STATISTIC_DATE.
*/
#define STATISTIC_LINE "date=%s epochsecs=%d nodeid=%u trans=%u commit=%u " \
"read=%u insert=%u attrinfo=%u cops=%u abort=%u"
/**
* Format of statistical information from the NDB Cluster.
* STATISTIC_LINE is sent on the statistical port from the Management server,
* each line is timestamped with STATISTIC_DATE.
*/
#define STATISTIC_DATE "%d-%.2d-%.2d/%.2d:%.2d:%.2d"
/**
* Format of statistical information from the NDB Cluster.
*/
#define OP_STATISTIC_LINE "date=%s epochsecs=%d nodeid=%d operations=%u"
/**
* The NdbMgmHandle.
*/
......
This diff is collapsed.
......@@ -250,17 +250,7 @@ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
sendSignal(subReq->blockRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
return;
}
/**
* If it's a new subscription, clear the loglevel
*
* Clear only if noOfEntries is 0, this is needed beacuse we set
* the default loglevels for the MGMT nodes during the inital connect phase.
* See reportConnected().
*/
if (subReq->noOfEntries == 0){
ptr.p->logLevel.clear();
}
ptr.p->logLevel.clear();
ptr.p->blockRef = subReq->blockRef;
}
......@@ -384,11 +374,6 @@ void Cmvmi::execCLOSE_COMREQ(Signal* signal)
globalTransporterRegistry.setIOState(i, HaltIO);
globalTransporterRegistry.do_disconnect(i);
/**
* Cancel possible event subscription
*/
cancelSubscription(i);
}
}
if (failNo != 0) {
......@@ -494,6 +479,8 @@ void Cmvmi::execDISCONNECT_REP(Signal *signal)
globalTransporterRegistry.do_connect(hostId);
}
cancelSubscription(hostId);
signal->theData[0] = EventReport::Disconnected;
signal->theData[1] = hostId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
......@@ -539,20 +526,6 @@ void Cmvmi::execCONNECT_REP(Signal *signal){
if(type == NodeInfo::MGM){
jam();
globalTransporterRegistry.setIOState(hostId, NoHalt);
EventSubscribeReq* dst = (EventSubscribeReq *)&signal->theData[0];
for (Uint32 i = 0; i < EventLogger::defEventLogMatrixSize; i++) {
dst->theCategories[i] = EventLogger::defEventLogMatrix[i].eventCategory;
dst->theLevels[i] = EventLogger::defEventLogMatrix[i].threshold;
}
dst->noOfEntries = EventLogger::defEventLogMatrixSize;
/* The BlockNumber is hardcoded as 1 in MgmtSrvr */
dst->blockRef = numberToRef(MIN_API_BLOCK_NO, hostId);
execEVENT_SUBSCRIBE_REQ(signal);
}
//------------------------------------------
......
......@@ -389,9 +389,9 @@ void CommandInterpreter::executeHelp(char* parameters) {
<< endl;
ndbout << "<category> = ";
for(i = 0; i<EventLogger::noOfEventCategoryNames; i++){
ndbout << EventLogger::eventCategoryNames[i].name;
if (i < EventLogger::noOfEventCategoryNames - 1) {
for(i = 0; i<EventLoggerBase::noOfEventCategoryNames; i++){
ndbout << EventLoggerBase::eventCategoryNames[i].name;
if (i < EventLoggerBase::noOfEventCategoryNames - 1) {
ndbout << " | ";
}
}
......@@ -831,12 +831,13 @@ void CommandInterpreter::executeStatus(int processId,
//*****************************************************************************
void CommandInterpreter::executeLogLevel(int processId,
const char* parameters, bool all) {
#if 0
(void)all; // Don't want compiler warning
SetLogLevelOrd logLevel; logLevel.clear();
if (emptyString(parameters) || (strcmp(parameters, "ALL") == 0)) {
for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++)
logLevel.setLogLevel(EventLogger::eventCategoryNames[i].category, 7);
for(Uint32 i = 0; i<EventLoggerBase::noOfEventCategoryNames; i++)
logLevel.setLogLevel(EventLoggerBase::eventCategoryNames[i].category, 7);
} else {
char * tmpString = strdup(parameters);
......@@ -852,7 +853,7 @@ void CommandInterpreter::executeLogLevel(int processId,
return;
}
LogLevel::EventCategory cat;
if(!EventLogger::matchEventCategory(categoryTxt,
if(!EventLoggerBase::matchEventCategory(categoryTxt,
&cat)){
ndbout << "Invalid loglevel specification, unknown category: "
<< categoryTxt << endl;
......@@ -875,6 +876,7 @@ void CommandInterpreter::executeLogLevel(int processId,
if (result != 0) {
ndbout << _mgmtSrvr.getErrorText(result) << endl;
}
#endif
}
......@@ -1080,12 +1082,13 @@ void CommandInterpreter::executeTestOff(int processId,
void CommandInterpreter::executeEventReporting(int processId,
const char* parameters,
bool all) {
#if 0
(void)all; // Don't want compiler warning
SetLogLevelOrd logLevel; logLevel.clear();
if (emptyString(parameters) || (strcmp(parameters, "ALL") == 0)) {
for(Uint32 i = 0; i<EventLogger::noOfEventCategoryNames; i++)
logLevel.setLogLevel(EventLogger::eventCategoryNames[i].category, 7);
for(Uint32 i = 0; i<EventLoggerBase::noOfEventCategoryNames; i++)
logLevel.setLogLevel(EventLoggerBase::eventCategoryNames[i].category, 7);
} else {
char * tmpString = strdup(parameters);
......@@ -1101,7 +1104,7 @@ void CommandInterpreter::executeEventReporting(int processId,
return;
}
LogLevel::EventCategory cat;
if(!EventLogger::matchEventCategory(categoryTxt,
if(!EventLoggerBase::matchEventCategory(categoryTxt,
&cat)){
ndbout << "Invalid loglevel specification, unknown category: "
<< categoryTxt << endl;
......@@ -1124,6 +1127,7 @@ void CommandInterpreter::executeEventReporting(int processId,
if (result != 0) {
ndbout << _mgmtSrvr.getErrorText(result) << endl;
}
#endif
}
void
......
......@@ -12,8 +12,6 @@ ndb_mgmd_SOURCES = \
main.cpp \
Services.cpp \
convertStrToInt.cpp \
NodeLogLevel.cpp \
NodeLogLevelList.cpp \
SignalQueue.cpp \
MgmtSrvrConfig.cpp \
ConfigInfo.cpp \
......
This diff is collapsed.
......@@ -28,8 +28,8 @@
#include <signaldata/ManagementServer.hpp>
#include "SignalQueue.hpp"
#include <ndb_version.h>
#include "NodeLogLevelList.hpp"
#include <EventLogger.hpp>
#include <signaldata/EventSubscribeReq.hpp>
/**
* @desc Block number for Management server.
......@@ -43,6 +43,29 @@ class Config;
class SetLogLevelOrd;
class SocketServer;
class MgmStatService : public EventLoggerBase
{
friend class MgmtSrvr;
public:
struct StatListener : public EventLoggerBase {
NDB_SOCKET_TYPE m_socket;
};
private:
class MgmtSrvr * m_mgmsrv;
MutexVector<StatListener> m_clients;
public:
MgmStatService(class MgmtSrvr * m) : m_clients(5) {
m_mgmsrv = m;
}
void add_listener(const StatListener&);
void log(int eventType, const Uint32* theData, NodeId nodeId);
void stopSessions();
};
/**
* @class MgmtSrvr
* @brief Main class for the management server.
......@@ -63,11 +86,6 @@ class SocketServer;
class MgmtSrvr {
public:
class StatisticsListner {
public:
virtual void println_statistics(const BaseString &s) = 0;
};
// some compilers need all of this
class Allocated_resources;
friend class Allocated_resources;
......@@ -84,11 +102,6 @@ public:
NodeBitmask m_reserved_nodes;
};
/**
* Set a reference to the socket server.
*/
void setStatisticsListner(StatisticsListner* listner);
/**
* Start/initate the event log.
*/
......@@ -150,15 +163,6 @@ public:
STATIC_CONST( OPERATION_IN_PROGRESS = 6667 );
STATIC_CONST( NO_CONTACT_WITH_DB_NODES = 5030 );
/**
* This class holds all statistical variables fetched with
* the getStatistics methods.
*/
class Statistics { // TODO, Real statistic data to be added
public:
int _test1;
};
/**
* This enum specifies the different signal loggig modes possible to set
* with the setSignalLoggingMode method.
......@@ -206,7 +210,7 @@ public:
typedef void (* EnterSingleCallback)(int nodeId, void * anyData,
int errorCode);
typedef void (* ExitSingleCallback)(int nodeId, void * anyData,
int errorCode);
int errorCode);
/**
* Lock configuration
......@@ -313,13 +317,6 @@ public:
bool abort = false,
int * stopCount = 0, StopCallback = 0, void * anyData = 0);
int setEventReportingLevel(int processId,
const class SetLogLevelOrd & logLevel,
bool isResend = false);
int startStatisticEventReporting(int level = 5);
struct BackupEvent {
enum Event {
BackupStarted = 1,
......@@ -377,22 +374,8 @@ public:
// INVALID_LEVEL
//**************************************************************************
/**
* Sets the Node's log level, i.e., its local event reporting.
*
* @param processId the DB node id.
* @param logLevel the log level.
* @param isResend Flag to indicate for resending log levels
* during node restart
* @return 0 if successful or NO_CONTACT_WITH_PROCESS,
* SEND_OR_RECEIVE_FAILED,
* COULD_NOT_ALLOCATE_MEMORY
*/
int setNodeLogLevel(int processId,
const class SetLogLevelOrd & logLevel,
bool isResend = false);
int setEventReportingLevelImpl(int processId, const EventSubscribeReq& ll);
int setNodeLogLevelImpl(int processId, const SetLogLevelOrd & ll);
/**
* Insert an error in a DB process.
......@@ -508,11 +491,6 @@ public:
*/
NodeId getPrimaryNode() const;
/**
* Returns the statistics port number.
* @return statistic port number.
*/
int getStatPort() const;
/**
* Returns the port number.
* @return port number.
......@@ -526,10 +504,7 @@ public:
private:
//**************************************************************************
int setEventReportingLevelImpl(int processId,
const class SetLogLevelOrd & logLevel,
bool isResend = false);
int setEventReportingLevel(int processId, LogLevel::EventCategory, Uint32);
/**
* Check if it is possible to send a signal to a (DB) process
......@@ -563,10 +538,6 @@ private:
Allocated_resources m_allocated_resources;
struct in_addr m_connect_address[MAX_NODES];
int _setVarReqResult; // The result of the SET_VAR_REQ response
Statistics _statistics; // handleSTATISTICS_CONF store the result here,
// and getStatistics reads it.
//**************************************************************************
// Specific signal handling methods
//**************************************************************************
......@@ -598,14 +569,6 @@ private:
// Returns: -
//**************************************************************************
int handleSTATISTICS_CONF(NdbApiSignal* signal);
//**************************************************************************
// Description: Handle reception of signal STATISTICS_CONF
// Parameters:
// signal: The recieved signal
// Returns: TODO, to be defined
//**************************************************************************
void handle_MGM_LOCK_CONFIG_REQ(NdbApiSignal *signal);
void handle_MGM_UNLOCK_CONFIG_REQ(NdbApiSignal *signal);
......@@ -631,7 +594,6 @@ private:
*/
enum WaitSignalType {
NO_WAIT, // We don't expect to receive any signal
WAIT_STATISTICS, // Accept STATISTICS_CONF
WAIT_SET_VAR, // Accept SET_VAR_CONF and SET_VAR_REF
WAIT_SUBSCRIBE_CONF, // Accept event subscription confirmation
WAIT_STOP,
......@@ -733,14 +695,6 @@ private:
class SignalQueue m_signalRecvQueue;
enum ndb_mgm_node_type nodeTypes[MAX_NODES];
int theConfCount; // The number of expected conf signals
StatisticsListner * m_statisticsListner; // Used for sending statistics info
bool _isStatPortActive;
bool _isClusterLogStatActive;
struct StopRecord {
StopRecord(){ inUse = false; callback = 0; singleUserMode = false;}
bool inUse;
......@@ -765,10 +719,16 @@ private:
void handleStopReply(NodeId nodeId, Uint32 errCode);
int translateStopRef(Uint32 errCode);
bool _isStopThread;
int _logLevelThreadSleep;
int _startedNodeId;
MutexVector<NodeId> m_started_nodes;
MutexVector<EventSubscribeReq> m_log_level_requests;
LogLevel m_nodeLogLevel[MAX_NODES];
enum ndb_mgm_node_type nodeTypes[MAX_NODES];
friend class MgmApiSession;
friend class MgmStatService;
MgmStatService m_statisticsListner;
/**
* Handles the thread wich upon a 'Node is started' event will
......@@ -782,15 +742,13 @@ private:
static void *signalRecvThread_C(void *);
void signalRecvThreadRun();
NodeLogLevelList* _nodeLogLevelList;
NodeLogLevelList* _clusterLogLevelList;
void backupCallback(BackupEvent &);
BackupCallback m_backupCallback;
BackupEvent m_lastBackupEvent;
Config *_props;
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
public:
/**
* This method does not exist
......
/* Copyright (C) 2003 MySQL AB
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 */
#include "NodeLogLevel.hpp"
// TODO_RONM: Clearly getCategory and getLevel is not correctly coded. Must be taken care of.
NodeLogLevel::NodeLogLevel(int nodeId, const SetLogLevelOrd& ll)
{
m_nodeId = nodeId;
m_logLevel = ll;
}
NodeLogLevel::~NodeLogLevel()
{
}
int
NodeLogLevel::getNodeId() const
{
return m_nodeId;
}
Uint32
NodeLogLevel::getCategory() const
{
for (Uint32 i = 0; i < m_logLevel.noOfEntries; i++)
{
return m_logLevel.theCategories[i];
}
return 0;
}
int
NodeLogLevel::getLevel() const
{
for (Uint32 i = 0; i < m_logLevel.noOfEntries; i++)
{
return m_logLevel.theLevels[i];
}
return 0;
}
void
NodeLogLevel::setLevel(int level)
{
for (Uint32 i = 0; i < m_logLevel.noOfEntries; i++)
{
m_logLevel.theLevels[i] = level;
}
}
SetLogLevelOrd
NodeLogLevel::getLogLevelOrd() const
{
return m_logLevel;
}
/* Copyright (C) 2003 MySQL AB
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 */
#ifndef NODELOGLEVEL_H
#define NODELOGLEVEL_H
#include <ndb_global.h>
#include <signaldata/SetLogLevelOrd.hpp>
/**
* Holds a DB node's log level settings for both local and event log levels.
* It only holds one log level setting even though SetLogLevelOrd can handle
* multiple log levels at once, it is not used in that way in the managment
* server.
*
* @version #@ $Id: NodeLogLevel.hpp,v 1.2 2003/07/05 17:40:22 elathal Exp $
*/
class NodeLogLevel
{
public:
NodeLogLevel(int nodeId, const SetLogLevelOrd& ll);
~NodeLogLevel();
int getNodeId() const;
Uint32 getCategory() const;
int getLevel() const;
void setLevel(int level);
SetLogLevelOrd getLogLevelOrd() const;
private:
NodeLogLevel();
NodeLogLevel(const NodeLogLevel&);
bool operator == (const NodeLogLevel&);
NodeLogLevel operator = (const NodeLogLevel&);
int m_nodeId;
SetLogLevelOrd m_logLevel;
};
#endif
/* Copyright (C) 2003 MySQL AB
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 */
#include <ndb_global.h>
#include "NodeLogLevelList.hpp"
#include "NodeLogLevel.hpp"
//
// PUBLIC
//
NodeLogLevelList::NodeLogLevelList() :
m_size(0),
m_pHeadNode(NULL),
m_pTailNode(NULL),
m_pCurrNode(NULL)
{
}
NodeLogLevelList::~NodeLogLevelList()
{
removeAll();
}
void
NodeLogLevelList::add(NodeLogLevel* pNewNode)
{
NodeLogLevelNode* pNode = new NodeLogLevelNode();
if (m_pHeadNode == NULL)
{
m_pHeadNode = pNode;
pNode->pPrev = NULL;
}
else
{
m_pTailNode->pNext = pNode;
pNode->pPrev = m_pTailNode;
}
m_pTailNode = pNode;
pNode->pNext = NULL;
pNode->pHandler = pNewNode;
m_size++;
}
bool
NodeLogLevelList::remove(NodeLogLevel* pRemoveNode)
{
NodeLogLevelNode* pNode = m_pHeadNode;
bool removed = false;
do
{
if (pNode->pHandler == pRemoveNode)
{
removeNode(pNode);
removed = true;
break;
}
} while ( (pNode = next(pNode)) != NULL);
return removed;
}
void
NodeLogLevelList::removeAll()
{
while (m_pHeadNode != NULL)
{
removeNode(m_pHeadNode);
}
}
NodeLogLevel*
NodeLogLevelList::next()
{
NodeLogLevel* pHandler = NULL;
if (m_pCurrNode == NULL)
{
m_pCurrNode = m_pHeadNode;
if (m_pCurrNode != NULL)
{
pHandler = m_pCurrNode->pHandler;
}
}
else
{
m_pCurrNode = next(m_pCurrNode); // Next node
if (m_pCurrNode != NULL)
{
pHandler = m_pCurrNode->pHandler;
}
}
return pHandler;
}
int
NodeLogLevelList::size() const
{
return m_size;
}
//
// PRIVATE
//
NodeLogLevelList::NodeLogLevelNode*
NodeLogLevelList::next(NodeLogLevelNode* pNode)
{
NodeLogLevelNode* pCurr = pNode;
if (pNode->pNext != NULL)
{
pCurr = pNode->pNext;
}
else
{
// Tail
pCurr = NULL;
}
return pCurr;
}
NodeLogLevelList::NodeLogLevelNode*
NodeLogLevelList::prev(NodeLogLevelNode* pNode)
{
NodeLogLevelNode* pCurr = pNode;
if (pNode->pPrev != NULL) // head
{
pCurr = pNode->pPrev;
}
else
{
// Head
pCurr = NULL;
}
return pCurr;
}
void
NodeLogLevelList::removeNode(NodeLogLevelNode* pNode)
{
if (pNode->pPrev == NULL) // If head
{
m_pHeadNode = pNode->pNext;
}
else
{
pNode->pPrev->pNext = pNode->pNext;
}
if (pNode->pNext == NULL) // if tail
{
m_pTailNode = pNode->pPrev;
}
else
{
pNode->pNext->pPrev = pNode->pPrev;
}
pNode->pNext = NULL;
pNode->pPrev = NULL;
delete pNode->pHandler; // Delete log handler
delete pNode;
m_size--;
}
/* Copyright (C) 2003 MySQL AB
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 */
#ifndef NODELOGLEVELLIST_H
#define NODELOGLEVELLIST_H
class NodeLogLevel;
/**
* Provides a simple linked list of NodeLogLevel.
*
* @see NodeLogLevel
* @version #@ $Id: NodeLogLevelList.hpp,v 1.1 2002/08/09 12:53:50 eyualex Exp $
*/
class NodeLogLevelList
{
public:
/**
* Default Constructor.
*/
NodeLogLevelList();
/**
* Destructor.
*/
~NodeLogLevelList();
/**
* Adds a new node.
*
* @param pNewHandler a new NodeLogLevel.
*/
void add(NodeLogLevel* pNewNode);
/**
* Removes a NodeLogLevel from the list and call its destructor.
*
* @param pRemoveHandler the NodeLogLevel to remove
*/
bool remove(NodeLogLevel* pRemoveNode);
/**
* Removes all items.
*/
void removeAll();
/**
* Returns the next node in the list.
* returns a node or NULL.
*/
NodeLogLevel* next();
/**
* Returns the size of the list.
*/
int size() const;
private:
/** List node */
struct NodeLogLevelNode
{
NodeLogLevelNode* pPrev;
NodeLogLevelNode* pNext;
NodeLogLevel* pHandler;
};
NodeLogLevelNode* next(NodeLogLevelNode* pNode);
NodeLogLevelNode* prev(NodeLogLevelNode* pNode);
void removeNode(NodeLogLevelNode* pNode);
int m_size;
NodeLogLevelNode* m_pHeadNode;
NodeLogLevelNode* m_pTailNode;
NodeLogLevelNode* m_pCurrNode;
};
#endif
......@@ -23,6 +23,7 @@
#include <mgmapi.h>
#include <EventLogger.hpp>
#include <signaldata/SetLogLevelOrd.hpp>
#include <LogLevel.hpp>
#include <BaseString.hpp>
#include <Base64.hpp>
......@@ -133,7 +134,7 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("public key", String, Mandatory, "Public key"),
MGM_CMD("get version", &MgmApiSession::getVersion, ""),
MGM_CMD("get status", &MgmApiSession::getStatus, ""),
MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
......@@ -236,7 +237,11 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("node", String, Mandatory, "Node"),
MGM_ARG("parameter", String, Mandatory, "Parameter"),
MGM_ARG("value", String, Mandatory, "Value"),
MGM_CMD("listen event", &MgmApiSession::listen_event, ""),
MGM_ARG("node", Int, Optional, "Node"),
MGM_ARG("filter", String, Mandatory, "Event category"),
MGM_END()
};
......@@ -289,7 +294,8 @@ MgmApiSession::runSession() {
break;
}
}
NDB_CLOSE_SOCKET(m_socket);
if(m_socket >= 0)
NDB_CLOSE_SOCKET(m_socket);
}
#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
......@@ -554,7 +560,7 @@ MgmApiSession::getStatPort(Parser_t::Context &,
const class Properties &) {
m_output->println("get statport reply");
m_output->println("tcpport: %d", m_mgmsrv.getStatPort());
m_output->println("tcpport: %d", 0);
m_output->println("");
}
......@@ -760,7 +766,6 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
BaseString categoryName, errorString;
SetLogLevelOrd logLevel;
int result;
logLevel.clear();
args.get("node", &node);
args.get("category", categoryName);
args.get("level", &level);
......@@ -779,14 +784,15 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
goto error;
}
logLevel.setLogLevel(category, level);
result = m_mgmsrv.setEventReportingLevel(node, logLevel);
EventSubscribeReq req;
req.blockRef = 0;
req.noOfEntries = 1;
req.theCategories[0] = category;
req.theLevels[0] = level;
m_mgmsrv.m_log_level_requests.push_back(req);
m_output->println("set cluster loglevel reply");
if(result != 0)
m_output->println("result: %s", m_mgmsrv.getErrorText(result));
else
m_output->println("result: Ok");
m_output->println("result: Ok");
m_output->println("");
return;
error:
......@@ -821,15 +827,15 @@ MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
goto error;
}
logLevel.setLogLevel(category, level);
result = m_mgmsrv.setNodeLogLevel(node, logLevel);
EventSubscribeReq req;
req.blockRef = node;
req.noOfEntries = 1;
req.theCategories[0] = category;
req.theLevels[0] = level;
m_mgmsrv.m_log_level_requests.push_back(req);
m_output->println("set loglevel reply");
if(result != 0)
m_output->println("result: %s", m_mgmsrv.getErrorText(result));
else
m_output->println("result: Ok");
m_output->println("result: Ok");
m_output->println("");
return;
error:
......@@ -1248,33 +1254,91 @@ MgmApiSession::configChange(Parser_t::Context &,
m_output->println("");
}
void
MgmStatService::println_statistics(const BaseString &line){
MutexVector<NDB_SOCKET_TYPE> copy(m_sockets.size());
m_sockets.lock();
NdbOut&
operator<<(NdbOut& out, const LogLevel & ll)
{
out << "[LogLevel: ";
for(size_t i = 0; i<_LOGLEVEL_CATEGORIES; i++)
out << ll.getLogLevel((LogLevel::EventCategory)i) << " ";
out << "]";
}
void
MgmStatService::log(int eventType, const Uint32* theData, NodeId nodeId){
Uint32 threshold = 0;
LogLevel::EventCategory cat;
for(unsigned i = 0; i<EventLogger::matrixSize; i++){
if(EventLogger::matrix[i].eventType == eventType){
cat = EventLogger::matrix[i].eventCategory;
threshold = EventLogger::matrix[i].threshold;
break;
}
}
char m_text[256];
EventLogger::getText(m_text, sizeof(m_text), eventType, theData, nodeId);
Vector<NDB_SOCKET_TYPE> copy;
m_clients.lock();
int i;
for(i = m_sockets.size() - 1; i >= 0; i--){
if(println_socket(m_sockets[i], MAX_WRITE_TIMEOUT, line.c_str()) == -1){
copy.push_back(m_sockets[i]);
m_sockets.erase(i, false);
for(i = m_clients.size() - 1; i >= 0; i--){
if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)){
if(m_clients[i].m_socket >= 0 &&
println_socket(m_clients[i].m_socket,
MAX_WRITE_TIMEOUT, m_text) == -1){
copy.push_back(m_clients[i].m_socket);
m_clients.erase(i, false);
}
}
}
m_sockets.unlock();
m_clients.unlock();
for(i = copy.size() - 1; i >= 0; i--){
for(i = 0; (unsigned)i<copy.size(); i++){
NDB_CLOSE_SOCKET(copy[i]);
copy.erase(i);
}
if(m_sockets.size() == 0 || false){
m_mgmsrv->startStatisticEventReporting(0);
if(copy.size()){
LogLevel tmp; tmp.clear();
m_clients.lock();
for(i = 0; i < m_clients.size(); i++){
tmp.set_max(m_clients[i].m_logLevel);
}
m_clients.unlock();
if(!(tmp == m_logLevel)){
m_logLevel = tmp;
EventSubscribeReq req;
req = tmp;
req.blockRef = 0;
m_mgmsrv->m_log_level_requests.push_back(req);
}
}
}
void
MgmStatService::add_listener(const StatListener& client){
m_clients.push_back(client);
LogLevel tmp = m_logLevel;
tmp.set_max(client.m_logLevel);
if(!(tmp == m_logLevel)){
m_logLevel = tmp;
EventSubscribeReq req;
req = tmp;
req.blockRef = 0;
m_mgmsrv->m_log_level_requests.push_back(req);
}
}
void
MgmStatService::stopSessions(){
for(int i = m_sockets.size() - 1; i >= 0; i--){
NDB_CLOSE_SOCKET(m_sockets[i]);
m_sockets.erase(i);
for(int i = m_clients.size() - 1; i >= 0; i--){
if(m_clients[i].m_socket >= 0){
NDB_CLOSE_SOCKET(m_clients[i].m_socket);
m_clients.erase(i);
}
}
}
......@@ -1298,6 +1362,71 @@ MgmApiSession::setParameter(Parser_t::Context &,
m_output->println("");
}
void
MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
Properties const & args) {
BaseString node, param, value;
args.get("node", node);
args.get("filter", param);
int result = 0;
BaseString msg;
MgmStatService::StatListener le;
le.m_socket = m_socket;
Vector<BaseString> list;
param.trim();
param.split(list, " ,");
for(size_t i = 0; i<list.size(); i++){
Vector<BaseString> spec;
list[i].trim();
list[i].split(spec, "=:");
if(spec.size() != 2){
msg.appfmt("Invalid filter specification: >%s< >%s< %d",
param.c_str(), list[i].c_str(), spec.size());
result = -1;
goto done;
}
spec[0].trim();
spec[0].ndb_toupper();
LogLevel::EventCategory category;
if(!EventLogger::matchEventCategory(spec[0].c_str(), &category)) {
msg.appfmt("Unknown category: >%s<", spec[0].c_str());
result = -1;
goto done;
}
int level = atoi(spec[1].c_str());
if(level < 0 || level > 15){
msg.appfmt("Invalid level: >%s<", spec[1].c_str());
result = -1;
goto done;
}
le.m_logLevel.setLogLevel(category, level);
}
if(list.size() == 0){
msg.appfmt("Empty filter specification");
result = -1;
goto done;
}
m_mgmsrv.m_statisticsListner.add_listener(le);
m_stop = true;
m_socket = -1;
done:
m_output->println("listen event");
m_output->println("result: %d", result);
if(result != 0)
m_output->println("msg: %s", msg.c_str());
}
template class MutexVector<int>;
template class Vector<ParserRow<MgmApiSession> const*>;
template class Vector<unsigned short>;
......@@ -83,7 +83,8 @@ public:
void configChange(Parser_t::Context &ctx, const class Properties &args);
void setParameter(Parser_t::Context &ctx, const class Properties &args);
void listen_event(Parser_t::Context &ctx, const class Properties &args);
void repCommand(Parser_t::Context &ctx, const class Properties &args);
};
......@@ -103,28 +104,4 @@ public:
}
};
class MgmStatService : public SocketServer::Service,
public MgmtSrvr::StatisticsListner
{
class MgmtSrvr * m_mgmsrv;
MutexVector<NDB_SOCKET_TYPE> m_sockets;
public:
MgmStatService() : m_sockets(5) {
m_mgmsrv = 0;
}
void setMgm(class MgmtSrvr * mgmsrv){
m_mgmsrv = mgmsrv;
}
SocketServer::Session * newSession(NDB_SOCKET_TYPE socket){
m_sockets.push_back(socket);
m_mgmsrv->startStatisticEventReporting(5);
return 0;
}
void stopSessions();
void println_statistics(const BaseString &line);
};
#endif
......@@ -70,7 +70,6 @@ struct MgmGlobals {
bool use_specific_ip;
char * interface_name;
int port;
int port_stats;
/** The configuration of the cluster */
Config * cluster_config;
......@@ -169,8 +168,6 @@ NDB_MAIN(mgmsrv){
MgmApiService * mapi = new MgmApiService();
MgmStatService * mstat = new MgmStatService();
/****************************
* Read configuration files *
****************************/
......@@ -230,13 +227,6 @@ NDB_MAIN(mgmsrv){
goto error_end;
}
if(!glob.socketServer->setup(mstat, glob.port_stats, glob.interface_name)){
ndbout_c("Unable to setup statistic port: %d!\nPlease check if the port"
" is already used.", glob.port_stats);
delete mstat;
goto error_end;
}
if(!glob.mgmObject->check_start()){
ndbout_c("Unable to check start management server.");
ndbout_c("Probably caused by illegal initial configuration file.");
......@@ -267,10 +257,7 @@ NDB_MAIN(mgmsrv){
}
//glob.mgmObject->saveConfig();
mstat->setMgm(glob.mgmObject);
mapi->setMgm(glob.mgmObject);
glob.mgmObject->setStatisticsListner(mstat);
char msg[256];
snprintf(msg, sizeof(msg),
......@@ -278,8 +265,8 @@ NDB_MAIN(mgmsrv){
ndbout_c(msg);
g_EventLogger.info(msg);
snprintf(msg, 256, "Id: %d, Command port: %d, Statistics port: %d",
glob.localNodeId, glob.port, glob.port_stats);
snprintf(msg, 256, "Id: %d, Command port: %d",
glob.localNodeId, glob.port);
ndbout_c(msg);
g_EventLogger.info(msg);
......@@ -309,7 +296,6 @@ NDB_MAIN(mgmsrv){
MgmGlobals::MgmGlobals(){
// Default values
port = 0;
port_stats = 0;
config_filename = NULL;
local_config_filename = NULL;
interface_name = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment