From 51be851d1253d4858f9b63c533df6bcfe76a393f Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 28 Feb 2015 21:18:53 +0000 Subject: [PATCH] Introduce Kernel thread and statistics git-svn-id: https://svn.argeo.org/commons/trunk@7992 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/log4j.properties | 1 + .../cms/internal/kernel/JackrabbitNode.java | 12 +- .../org/argeo/cms/internal/kernel/Kernel.java | 17 ++- .../cms/internal/kernel/KernelThread.java | 123 ++++++++++++++++++ 4 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java diff --git a/demo/log4j.properties b/demo/log4j.properties index 122f42a67..8b071c036 100644 --- a/demo/log4j.properties +++ b/demo/log4j.properties @@ -1,6 +1,7 @@ log4j.rootLogger=WARN, development log4j.logger.org.argeo=DEBUG +#log4j.logger.argeo.stats=DEBUG ## Appenders log4j.appender.console=org.apache.log4j.ConsoleAppender diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java index 5e8669e4b..c9c100e12 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java @@ -20,6 +20,7 @@ import org.apache.jackrabbit.core.RepositoryImpl; import org.apache.jackrabbit.core.cache.CacheManager; import org.apache.jackrabbit.core.config.RepositoryConfig; import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; +import org.apache.jackrabbit.stats.RepositoryStatisticsImpl; import org.argeo.ArgeoException; import org.argeo.cms.CmsException; import org.argeo.jackrabbit.JackrabbitWrapper; @@ -34,7 +35,6 @@ class JackrabbitNode extends JackrabbitWrapper implements KernelConstants, ArgeoJcrConstants { private static Log log = LogFactory.getLog(JackrabbitNode.class); - @SuppressWarnings("unused") private RepositoryContext repositoryContext; private ServiceRegistration repositoryReg; @@ -66,11 +66,15 @@ class JackrabbitNode extends JackrabbitWrapper implements KernelConstants, ((RepositoryImpl) getRepository()).shutdown(); } - Dictionary getDefaults() { - return KernelUtils.asDictionary(getClass().getClassLoader(), - "/org/argeo/cms/internal/kernel/jackrabbit-node.properties"); + RepositoryStatisticsImpl getRepositoryStatistics() { + return repositoryContext.getRepositoryStatistics(); } + // Dictionary getDefaults() { + // return KernelUtils.asDictionary(getClass().getClassLoader(), + // "/org/argeo/cms/internal/kernel/jackrabbit-node.properties"); + // } + private RepositoryConfig getConfiguration(JackrabbitNodeType type, Hashtable vars) throws RepositoryException { ClassLoader cl = getClass().getClassLoader(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java index c63184a24..af4f0ff2a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java @@ -39,10 +39,12 @@ final class Kernel implements ServiceListener { private final BundleContext bundleContext = Activator.getBundleContext(); - private JackrabbitNode node; - private OsgiJackrabbitRepositoryFactory repositoryFactory; - private NodeSecurity nodeSecurity; - private NodeHttp nodeHttp; + ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName()); + JackrabbitNode node; + OsgiJackrabbitRepositoryFactory repositoryFactory; + NodeSecurity nodeSecurity; + NodeHttp nodeHttp; + private KernelThread kernelThread; void init() { ClassLoader currentContextCl = Thread.currentThread() @@ -68,6 +70,11 @@ final class Kernel implements ServiceListener { ExtendedHttpService httpService = waitForHttpService(); nodeHttp = new NodeHttp(httpService, node, nodeSecurity); + // Kernel thread + kernelThread = new KernelThread(this); + kernelThread.setContextClassLoader(Kernel.class.getClassLoader()); + kernelThread.start(); + // Publish services to OSGi nodeSecurity.publish(); node.publish(repositoryFactory); @@ -94,6 +101,8 @@ final class Kernel implements ServiceListener { void destroy() { long begin = System.currentTimeMillis(); + kernelThread.destroyAndJoin(); + if (nodeHttp != null) nodeHttp.destroy(); if (nodeSecurity != null) diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java new file mode 100644 index 000000000..e58cbeef1 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java @@ -0,0 +1,123 @@ +package org.argeo.cms.internal.kernel; + +import java.io.File; +import java.lang.management.ManagementFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.stats.RepositoryStatistics; +import org.apache.jackrabbit.stats.RepositoryStatisticsImpl; +import org.argeo.cms.CmsException; + +/** + * Background thread started by the {@link Kernel}, which gather statistics and + * monitor/control other processes. + */ +class KernelThread extends Thread { + @SuppressWarnings("unused") + private final Kernel kernel; + private final RepositoryStatisticsImpl repoStats; + + /** The smallest period of operation, in ms */ + private final long PERIOD = 60 * 1000l; + /** One ms in ns */ + private final static long m = 1000l * 1000l; + private final static long M = 1024l * 1024l; + + private boolean running = true; + + private Log kernelStatsLog = LogFactory.getLog("argeo.stats.kernel"); + private Log nodeStatsLog = LogFactory.getLog("argeo.stats.node"); + + @SuppressWarnings("unused") + private long cycle = 0l; + + public KernelThread(Kernel kernel) { + super(kernel.threadGroup, kernel.getClass().getSimpleName()); + this.kernel = kernel; + this.repoStats = kernel.node.getRepositoryStatistics(); + } + + private void doSmallestPeriod() { + if (kernelStatsLog.isDebugEnabled()) { + StringBuilder line = new StringBuilder(64); + line.append("§\t"); + long freeMem = Runtime.getRuntime().freeMemory() / M; + long totalMem = Runtime.getRuntime().totalMemory() / M; + long maxMem = Runtime.getRuntime().maxMemory() / M; + double loadAvg = ManagementFactory.getOperatingSystemMXBean() + .getSystemLoadAverage(); + // in min + boolean min = true; + long uptime = ManagementFactory.getRuntimeMXBean().getUptime() + / (1000 * 60); + if (uptime > 24 * 60) { + min = false; + uptime = uptime / 60; + } + line.append(uptime).append(min ? " min" : " h").append('\t'); + line.append(loadAvg).append('\t').append(maxMem).append('\t') + .append(totalMem).append('\t').append(freeMem).append('\t'); + kernelStatsLog.debug(line); + } + + if (nodeStatsLog.isDebugEnabled()) { + File dataDir = KernelUtils.getOsgiInstanceDir(); + long freeSpace = dataDir.getUsableSpace() / M; + // File currentRoot = null; + // for (File root : File.listRoots()) { + // String rootPath = root.getAbsolutePath(); + // if (dataDir.getAbsolutePath().startsWith(rootPath)) { + // if (currentRoot == null + // || (rootPath.length() > currentRoot.getPath() + // .length())) { + // currentRoot = root; + // } + // } + // } + // long totalSpace = currentRoot.getTotalSpace(); + StringBuilder line = new StringBuilder(128); + line.append("§\t").append(freeSpace) + .append(" MB left in " + dataDir); + line.append('\n'); + for (RepositoryStatistics.Type type : RepositoryStatistics.Type + .values()) { + long[] vals = repoStats.getTimeSeries(type).getValuePerMinute(); + long val = vals[vals.length - 1]; + line.append(type.name()).append('\t').append(val).append('\n'); + } + nodeStatsLog.debug(line); + } + } + + @Override + public void run() { + final long periodNs = PERIOD * m; + while (running) { + long beginNs = System.nanoTime(); + doSmallestPeriod(); + + long waitNs = periodNs - (System.nanoTime() - beginNs); + if (waitNs < 0) + continue; + // wait + try { + sleep(waitNs / m, (int) (waitNs % m)); + } catch (InterruptedException e) { + // silent + } + cycle++; + } + } + + synchronized void destroyAndJoin() { + running = false; + notifyAll(); + interrupt(); + try { + join(PERIOD * 2); + } catch (InterruptedException e) { + throw new CmsException("Kernel thread destruction was interrupted"); + } + } +} -- 2.30.2