MXS-2050 Prepare to move file handling inside router sessions

The sessions will need to reopen the log file if it's rotated.
This commit is contained in:
Esa Korhonen 2019-02-08 11:13:30 +02:00
parent eac478876d
commit 16641a1f46
2 changed files with 87 additions and 97 deletions

View File

@ -113,8 +113,7 @@ QlaInstance::QlaInstance(const string& name, MXS_CONFIG_PARAMETER* params)
}
QlaInstance::Settings::Settings(MXS_CONFIG_PARAMETER* params)
: log_mode_flags(params->get_enum(PARAM_LOG_TYPE, log_type_values))
, log_file_data_flags(params->get_enum(PARAM_LOG_DATA, log_data_values))
: log_file_data_flags(params->get_enum(PARAM_LOG_DATA, log_data_values))
, filebase(params->get_string(PARAM_FILEBASE))
, flush_writes(params->get_bool(PARAM_FLUSH))
, append(params->get_bool(PARAM_APPEND))
@ -125,6 +124,9 @@ QlaInstance::Settings::Settings(MXS_CONFIG_PARAMETER* params)
, match(params->get_string(PARAM_MATCH))
, exclude(params->get_string(PARAM_EXCLUDE))
{
auto log_file_types = params->get_enum(PARAM_LOG_TYPE, log_type_values);
write_session_log = (log_file_types & CONFIG_FILE_SESSION);
write_unified_log = (log_file_types & CONFIG_FILE_UNIFIED);
}
QlaInstance::~QlaInstance()
@ -137,19 +139,12 @@ QlaInstance::~QlaInstance()
}
}
QlaFilterSession::QlaFilterSession(const char* user, const char* remote, bool ses_active,
pcre2_match_data* mdata,
const string& ses_filename, FILE* ses_file,
size_t ses_id, const char* service, QlaInstance& instance)
QlaFilterSession::QlaFilterSession(QlaInstance& instance, MXS_SESSION* session)
: m_instance(instance)
, m_user(user)
, m_remote(remote)
, m_active(ses_active)
, m_mdata(mdata)
, m_filename(ses_filename)
, m_logfile(ses_file)
, m_ses_id(ses_id)
, m_service(service)
, m_user(session_get_user(session))
, m_remote(session_get_remote(session))
, m_service(session->service->name)
, m_ses_id(session->ses_id)
{
}
@ -162,7 +157,7 @@ QlaFilterSession::~QlaFilterSession()
void QlaFilterSession::close()
{
if (m_active && m_logfile)
if (m_logfile)
{
fclose(m_logfile);
m_logfile = nullptr;
@ -197,7 +192,7 @@ QlaInstance* QlaInstance::create(const std::string name, MXS_CONFIG_PARAMETER* p
my_instance->m_re_exclude = re_exclude;
my_instance->m_ovec_size = ovec_size;
// Try to open the unified log file
if (my_instance->m_settings.log_mode_flags & CONFIG_FILE_UNIFIED)
if (my_instance->m_settings.write_unified_log)
{
string unified_filename = my_instance->m_settings.filebase + ".unified";
// Open the file. It is only closed at program exit.
@ -239,80 +234,68 @@ QlaInstance* QlaInstance::create(const std::string name, MXS_CONFIG_PARAMETER* p
QlaFilterSession* QlaInstance::newSession(MXS_SESSION* session)
{
// Need the following values before session constructor
const char* remote = session_get_remote(session);
const char* userName = session_get_user(session);
pcre2_match_data* mdata = NULL;
bool ses_active = true;
string filename;
FILE* session_file = NULL;
bool error = false;
mxb_assert(userName && remote);
if ((!m_settings.source.empty() && remote && m_settings.source != remote)
|| (!m_settings.user_name.empty() && userName && m_settings.user_name != userName))
auto my_session = new (std::nothrow) QlaFilterSession(*this, session);
if (my_session)
{
ses_active = false;
}
if (m_ovec_size > 0)
{
mdata = pcre2_match_data_create(m_ovec_size, NULL);
if (mdata == NULL)
if (!my_session->prepare())
{
// Can this happen? Would require pcre2 to fail completely.
MXS_ERROR("pcre2_match_data_create returned NULL.");
error = true;
}
}
// Only open the session file if the corresponding mode setting is used
if (!error && ses_active && m_settings.log_mode_flags & CONFIG_FILE_SESSION)
{
filename = mxb::string_printf("%s.%" PRIu64, m_settings.filebase.c_str(), session->ses_id);
// Session numbers are not printed to session files
uint32_t data_flags = (m_settings.log_file_data_flags & ~LOG_DATA_SESSION);
session_file = open_log_file(data_flags, filename.c_str());
if (session_file == NULL)
{
MXS_ERROR("Opening output file for qla-filter failed due to %d, %s",
errno,
mxs_strerror(errno));
error = true;
}
}
QlaFilterSession* my_session = NULL;
if (!error)
{
my_session = new(std::nothrow) QlaFilterSession(userName, remote, ses_active, mdata,
filename, session_file,
session->ses_id, session->service->name,
*this);
if (my_session == NULL)
{
error = true;
}
}
if (error)
{
pcre2_match_data_free(mdata);
if (session_file)
{
fclose(session_file);
my_session->close();
delete my_session;
my_session = nullptr;
}
}
return my_session;
}
bool QlaFilterSession::prepare()
{
const auto& settings = m_instance.m_settings;
bool hostname_ok = settings.source.empty() || (m_remote == settings.source);
bool username_ok = settings.user_name.empty() || (m_user == settings.user_name);
m_active = hostname_ok && username_ok;
bool error = false;
if (m_active)
{
auto ovec_size = m_instance.m_ovec_size;
if (ovec_size > 0)
{
m_mdata = pcre2_match_data_create(ovec_size, NULL);
if (!m_mdata)
{
MXS_ERROR("pcre2_match_data_create returned NULL.");
error = true;
}
}
// Only open the session file if the corresponding mode setting is used.
if (!error && settings.write_session_log)
{
string filename = mxb::string_printf("%s.%" PRIu64, settings.filebase.c_str(), m_ses_id);
// Session numbers are not printed to session files.
uint32_t data_flags = (settings.log_file_data_flags & ~LOG_DATA_SESSION);
m_logfile = m_instance.open_log_file(data_flags, filename.c_str());
if (m_logfile)
{
m_filename = filename;
}
else
{
MXS_ERROR("Opening output file %s' for qla-filter failed due to %d, %s",
filename.c_str(), errno, mxs_strerror(errno));
error = true;
}
}
}
return !error;
}
bool QlaInstance::read_to_json(int start, int end, json_t** output) const
{
bool rval = false;
if (m_settings.log_mode_flags & CONFIG_FILE_UNIFIED)
if (m_settings.write_unified_log)
{
mxb_assert(m_unified_fp && !m_unified_filename.empty());
std::ifstream file(m_unified_filename);
@ -417,7 +400,7 @@ void QlaFilterSession::write_log_entries(const char* date_string, const char* qu
int elapsed_ms)
{
bool write_error = false;
if (m_instance.m_settings.log_mode_flags & CONFIG_FILE_SESSION)
if (m_instance.m_settings.write_session_log)
{
// In this case there is no need to write the session
// number into the files.
@ -432,7 +415,7 @@ void QlaFilterSession::write_log_entries(const char* date_string, const char* qu
write_error = true;
}
}
if (m_instance.m_settings.log_mode_flags & CONFIG_FILE_UNIFIED)
if (m_instance.m_settings.write_unified_log)
{
uint32_t data_flags = m_instance.m_settings.log_file_data_flags;
if (write_log_entry(m_instance.m_unified_fp,

View File

@ -104,6 +104,7 @@ public:
void diagnostics(DCB* dcb) const;
json_t* diagnostics_json() const;
FILE* open_log_file(uint32_t, const char*);
const std::string m_name; /* Filter definition name */
@ -122,7 +123,8 @@ public:
public:
Settings(MXS_CONFIG_PARAMETER* params);
uint32_t log_mode_flags {0}; /* Log file mode settings */
bool write_unified_log {false};
bool write_session_log {false};
uint32_t log_file_data_flags {0}; /* What data is saved to the files */
std::string filebase; /* The filename base */
bool flush_writes {false}; /* Flush log file after every write? */
@ -136,9 +138,6 @@ public:
};
Settings m_settings;
private:
FILE* open_log_file(uint32_t, const char*);
};
/* The session structure for this QLA filter. */
@ -147,11 +146,16 @@ class QlaFilterSession : public MXS_FILTER_SESSION
public:
QlaFilterSession(const QlaFilterSession&);
QlaFilterSession& operator=(const QlaFilterSession&);
QlaFilterSession(const char* user, const char* remote, bool ses_active,
pcre2_match_data* mdata, const std::string& ses_filename, FILE* ses_file,
size_t ses_id, const char* service, QlaInstance& instance);
QlaFilterSession(QlaInstance& instance, MXS_SESSION* session);
~QlaFilterSession();
/**
* Prepares a session for routing. Checks if username and/or host match and opens the log file.
*
* @return True on success. If false is returned, the session should be closed and deleted.
*/
bool prepare();
/**
* Route a query.
*
@ -175,14 +179,17 @@ public:
QlaInstance& m_instance;
const char* m_user; /* Client username */
const char* m_remote; /* Client address */
bool m_active; /* Is session active? */
pcre2_match_data* m_mdata; /* Regex match data */
std::string m_filename; /* The session-specific log file name */
FILE* m_logfile; /* The session-specific log file */
size_t m_ses_id; /* The session this filter session serves. */
const char* m_service; /* The service name this filter is attached to. */
const std::string m_user; /* Client username */
const std::string m_remote; /* Client address */
const std::string m_service; /* The service name this filter is attached to. */
const uint64_t m_ses_id {0}; /* The session this filter session serves. */
bool m_active {false}; /* Is session active? */
pcre2_match_data* m_mdata {nullptr}; /* Regex match data */
std::string m_filename; /* The session-specific log file name */
FILE* m_logfile {nullptr}; /* The session-specific log file */
LogEventData m_event_data; /* Information about the latest event, used if logging execution time. */
MXS_UPSTREAM up;