MaxScale/server/core/event.cc
Niclas Antti c447e5cf15 Uncrustify maxscale
See script directory for method. The script to run in the top level
MaxScale directory is called maxscale-uncrustify.sh, which uses
another script, list-src, from the same directory (so you need to set
your PATH). The uncrustify version was 0.66.
2018-09-09 22:26:19 +03:00

492 lines
9.8 KiB
C++

/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2022-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#include "internal/event.hh"
#include <algorithm>
#include <string.h>
#include <maxbase/assert.h>
#include <maxbase/atomic.h>
using namespace std;
namespace
{
using namespace maxscale;
const char CN_UNKNOWN[] = "Unknown";
const char CN_FACILITY[] = "facility";
const char CN_LEVEL[] = "level";
const char CN_AUTHENTICATION_FAILURE[] = "authentication_failure";
const char EVENT_PREFIX[] = "event.";
struct NAME_AND_VALUE
{
const char* zName;
int32_t value;
};
int name_and_value_compare(const void* pLeft, const void* pRight)
{
const NAME_AND_VALUE* pL = static_cast<const NAME_AND_VALUE*>(pLeft);
const NAME_AND_VALUE* pR = static_cast<const NAME_AND_VALUE*>(pRight);
return strcmp(pL->zName, pR->zName);
}
// Keep these in alphabetical order.
const NAME_AND_VALUE levels[] =
{
{
"LOG_ALERT",
LOG_ALERT,
},
{
"LOG_CRIT",
LOG_CRIT,
},
{
"LOG_DEBUG",
LOG_DEBUG,
},
{
"LOG_EMER",
LOG_EMERG,
},
{
"LOG_ERR",
LOG_ERR,
},
{
"LOG_INFO",
LOG_INFO,
},
{
"LOG_NOTICE",
LOG_NOTICE,
},
{
"LOG_WARNING",
LOG_WARNING,
},
};
const int N_LEVELS = sizeof(levels) / sizeof(levels[0]);
// Keep these in alphabetical order.
const NAME_AND_VALUE facilities[] =
{
{
"LOG_AUTH",
LOG_AUTH
},
{
"LOG_AUTHPRIV",
LOG_AUTHPRIV
},
{
"LOG_CRON",
LOG_CRON
},
{
"LOG_DAEMON",
LOG_DAEMON
},
{
"LOG_FTP",
LOG_FTP
},
{
"LOG_KERN",
LOG_KERN
},
{
"LOG_LOCAL0",
LOG_LOCAL0
},
{
"LOG_LOCAL1",
LOG_LOCAL1
},
{
"LOG_LOCAL2",
LOG_LOCAL2
},
{
"LOG_LOCAL3",
LOG_LOCAL3
},
{
"LOG_LOCAL4",
LOG_LOCAL4
},
{
"LOG_LOCAL5",
LOG_LOCAL5
},
{
"LOG_LOCAL6",
LOG_LOCAL6
},
{
"LOG_LOCAL7",
LOG_LOCAL0
},
{
"LOG_LPR",
LOG_LPR
},
{
"LOG_MAIL",
LOG_MAIL
},
{
"LOG_NEWS",
LOG_NEWS
},
{
"LOG_SYSLOG",
LOG_SYSLOG
},
{
"LOG_USER",
LOG_USER
},
{
"LOG_UUCP",
LOG_UUCP
},
};
const int N_FACILITIES = sizeof(facilities) / sizeof(facilities[0]);
struct EVENT
{
const char* zName;
event::id_t id;
int32_t facility;
int32_t level;
};
// Keep these in alphabetical order.
EVENT events[] =
{
{
CN_AUTHENTICATION_FAILURE,
event::AUTHENTICATION_FAILURE,
event::DEFAULT_FACILITY,
event::DEFAULT_LEVEL
}
};
const int N_EVENTS = sizeof(events) / sizeof(events[0]);
int event_compare(const void* pLeft, const void* pRight)
{
const EVENT* pL = static_cast<const EVENT*>(pLeft);
const EVENT* pR = static_cast<const EVENT*>(pRight);
return strcmp(pL->zName, pR->zName);
}
struct
{
EVENT* events;
const NAME_AND_VALUE* levels;
const NAME_AND_VALUE* facilities;
} this_unit =
{
events,
levels,
facilities
};
event::result_t configure_facility(event::id_t id, const char* zValue)
{
event::result_t rv = event::INVALID;
int32_t facility;
if (log_facility_from_string(&facility, zValue))
{
event::set_log_facility(id, facility);
rv = event::ACCEPTED;
}
else
{
MXS_ERROR("%s is not a valid facility.", zValue);
}
return rv;
}
event::result_t configure_level(event::id_t id, const char* zValue)
{
event::result_t rv = event::INVALID;
int32_t level;
if (log_level_from_string(&level, zValue))
{
event::set_log_level(id, level);
rv = event::ACCEPTED;
}
else
{
MXS_ERROR("%s is not a valid level.", zValue);
}
return rv;
}
}
namespace maxscale
{
const char* log_level_to_string(int32_t level)
{
auto begin = this_unit.levels;
auto end = begin + N_LEVELS;
auto i = find_if(begin,
end,
[level](const NAME_AND_VALUE& item) -> bool {
return item.value == level;
});
return i == end ? CN_UNKNOWN : i->zName;
}
bool log_level_from_string(int32_t* pLevel, const char* zValue)
{
NAME_AND_VALUE key = {zValue};
void* pResult = bsearch(&key,
this_unit.levels,
N_LEVELS,
sizeof(NAME_AND_VALUE),
name_and_value_compare);
if (pResult)
{
const NAME_AND_VALUE* pItem = static_cast<const NAME_AND_VALUE*>(pResult);
*pLevel = pItem->value;
}
return pResult != nullptr;
}
const char* log_facility_to_string(int32_t facility)
{
auto begin = this_unit.facilities;
auto end = begin + N_FACILITIES;
auto i = find_if(begin,
end,
[facility](const NAME_AND_VALUE& item) -> bool {
return item.value == facility;
});
return i == end ? CN_UNKNOWN : i->zName;
}
bool log_facility_from_string(int32_t* pFacility, const char* zValue)
{
NAME_AND_VALUE key = {zValue};
void* pResult = bsearch(&key,
this_unit.facilities,
N_FACILITIES,
sizeof(NAME_AND_VALUE),
name_and_value_compare);
if (pResult)
{
const NAME_AND_VALUE* pItem = static_cast<const NAME_AND_VALUE*>(pResult);
*pFacility = pItem->value;
}
return pResult != nullptr;
}
namespace event
{
const char* to_string(id_t id)
{
auto begin = this_unit.events;
auto end = begin + N_EVENTS;
auto i = find_if(begin,
end,
[id](const EVENT& item) -> bool {
return item.id == id;
});
return i == end ? CN_UNKNOWN : i->zName;
}
bool from_string(id_t* pId, const char* zValue)
{
EVENT key = {zValue};
void* pResult = bsearch(&key,
this_unit.events,
N_EVENTS,
sizeof(EVENT),
event_compare);
if (pResult)
{
const EVENT* pItem = static_cast<const EVENT*>(pResult);
*pId = pItem->id;
}
return pResult != nullptr;
}
void set_log_facility(id_t id, int32_t facility)
{
bool rv = false;
mxb_assert((id >= 0) && (id < N_EVENTS));
// We silently strip away other than the relevant bits.
facility = facility & LOG_FACMASK;
EVENT& event = this_unit.events[id];
atomic_store_int32(&event.facility, facility);
}
int32_t get_log_facility(id_t id)
{
mxb_assert((id >= 0) && (id < N_EVENTS));
const EVENT& event = this_unit.events[id];
return atomic_load_int32(&event.facility);
}
void set_log_level(id_t id, int32_t level)
{
mxb_assert((id >= 0) && (id < N_EVENTS));
// We silently strip away other than the relevant bits.
level = level & LOG_PRIMASK;
EVENT& event = this_unit.events[id];
atomic_store_int32(&event.level, level);
}
int32_t get_log_level(id_t id)
{
mxb_assert((id >= 0) && (id < N_EVENTS));
const EVENT& event = this_unit.events[id];
return atomic_load_int32(&event.level);
}
result_t configure(const char* zName, const char* zValue)
{
result_t rv = IGNORED;
if (strncmp(zName, EVENT_PREFIX, sizeof(EVENT_PREFIX) - 1) == 0)
{
rv = INVALID;
string name(zName + sizeof(EVENT_PREFIX) - 1); // Character following '.'
auto i = name.find_first_of('.');
if (i != string::npos)
{
string event = name.substr(0, i);
string property = name.substr(i + 1);
id_t id;
if (from_string(&id, event.c_str()))
{
mxb_assert((id >= 0) && (id < N_EVENTS));
if (property == CN_FACILITY)
{
rv = configure_facility(id, zValue);
}
else if (property == CN_LEVEL)
{
rv = configure_level(id, zValue);
}
else
{
MXS_ERROR("%s is neither %s nor %s.", property.c_str(), CN_FACILITY, CN_LEVEL);
}
}
else
{
MXS_ERROR("%s does not refer to a known event.", zValue);
}
}
else
{
MXS_ERROR("%s is not a valid event configuration.", zName);
}
}
return rv;
}
void log(id_t event_id,
const char* modname,
const char* file,
int line,
const char* function,
const char* format,
...)
{
va_list valist;
mxb_assert((event_id >= 0) && (event_id < N_EVENTS));
const EVENT& event = this_unit.events[event_id];
int priority = atomic_load_int32(&event.facility) | atomic_load_int32(&event.level);
va_start(valist, format);
int len = vsnprintf(NULL, 0, format, valist);
va_end(valist);
if (len > BUFSIZ)
{
len = BUFSIZ;
}
char message[len + 1];
va_start(valist, format);
vsnprintf(message, len + 1, format, valist);
va_end(valist);
mxs_log_message(priority, modname, file, line, function, "%s", message);
}
} // event
} // maxscale