SQLQueryCounterConfiguration.java
/*
** Module : SQLQueryCounterConfiguration.java
** Abstract : Reading configuration for QueryCounterJMX.
**
** Copyright (c) 2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
** 001 ICP 20241111 First revision with basic usage.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.persist.orm;
import static com.goldencode.p2j.util.logging.LoggingUtil.resolveLogFile;
import com.goldencode.p2j.directory.DirectoryService;
import com.goldencode.p2j.jmx.*;
import com.goldencode.p2j.main.ClientCore;
import com.goldencode.p2j.util.Utils;
import com.goldencode.p2j.util.logging.CentralLogger;
import java.util.*;
import java.util.function.Supplier;
import java.util.logging.Level;
/**
* Class responsible with reading configuration for {@link QueryCounterJMX}.
*/
public final class SQLQueryCounterConfiguration {
/** Map to hold the configuration for each database. */
private static final Map<String, SQLQueryCounterConfiguration> configs = new HashMap<>();
/** Logger. */
private static final CentralLogger LOG = CentralLogger.get(SQLQueryCounterConfiguration.class);
/** Global directory path, used if a local one does not exist. */
private static final String GLOBAL_DIR_PATH = "persistence/query-counting";
/** Singleton instance of {@link QueryCounterJMX} for managing query counting operations. */
private static final QueryCounterJMX SIMPLE_QUERY_COUNTER =
QueryCounterJMX.getInstance(FwdServerJMX.QueryCounterEnum.QueryCounter);
/** Flag to enable or disable query counting. */
private boolean enableCounting;
/** The file that will receive the logging output. */
private String outputFile;
/**
* Constructor of a configuration.
*
* Enables logging based on the directory configuration.
*
* @param databaseName
* The name of the database in use.
*/
private SQLQueryCounterConfiguration(String databaseName)
{
boolean enableQueryCounting = false;
String outputFile = null;
String directoryPath = null;
boolean hasLocalConfiguration = false;
String localdirectoryPath = "database/" + databaseName + "/query-counting";
String defaultOutputFile = "%db_querycount.csv";
DirectoryService ds = DirectoryService.getInstance();
if (ds != null)
{
try
{
if (!ds.bind())
{
LOG.warning("Query counting configuration is not enabled");
}
String isCountingEnabled = Utils.getDirectoryNodeString(ds,
localdirectoryPath + "/enabled",
"NULL",
false);
switch (isCountingEnabled.toUpperCase())
{
case "NULL":
String globalPath = GLOBAL_DIR_PATH + "/enabled";
enableQueryCounting = Boolean.parseBoolean(Utils.getDirectoryNodeString(ds,
globalPath,
"FALSE",
false));
break;
case "TRUE":
enableQueryCounting = true;
hasLocalConfiguration = true;
break;
case "FALSE":
enableQueryCounting = false;
hasLocalConfiguration = true;
break;
default:
throw new RuntimeException("Invalid value for attribute: enabled");
}
}
finally
{
ds.unbind();
}
}
enableCounting = enableQueryCounting;
if (enableCounting)
{
directoryPath = hasLocalConfiguration ? localdirectoryPath : GLOBAL_DIR_PATH;
outputFile = Utils.getDirectoryNodeString(ds,
directoryPath + "/output-to-file",
defaultOutputFile,
false);
}
Supplier<Long> processIdSupplier = () ->
{
try
{
System.loadLibrary("p2j");
return ClientCore.getPid();
}
catch (Throwable t)
{
LOG.log(Level.FINE, "", t);
return 0L;
}
};
String formattedFilePath = resolveLogFile(outputFile,
processIdSupplier,
"server",
databaseName,
true);
outputFile = formattedFilePath;
SIMPLE_QUERY_COUNTER.updateConfiguration(databaseName, new QueryCountConfiguration(enableCounting, outputFile));
}
/**
* Get the query counting configuration of a specific database.
*
* @param databaseName
* The name of the database in use.
*
* @return SQLQueryCounterConfiguration
* If it exists, an already created configuration for that database, or a new one otherwise.
*/
public static QueryCountConfiguration getConfiguration(String databaseName)
{
SQLQueryCounterConfiguration sqlConfig = configs.computeIfAbsent(databaseName, SQLQueryCounterConfiguration::new);
return new QueryCountConfiguration(sqlConfig.isQueryCountingEnabled(), sqlConfig.getOutputFile());
}
/**
* Getter for the {@code enableCounting} field.
*
* @return boolean
* The value of {@code enableCounting}.
*/
public boolean isQueryCountingEnabled()
{
return enableCounting;
}
/**
* Getter for the {@code outputFile} field.
*
* @return String
* The value of {@code outputFile}.
*/
public String getOutputFile()
{
return outputFile;
}
}