X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FKernelThread.java;fp=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FKernelThread.java;h=e58cbeef1959654589c80b44699bceca27e13be5;hb=51be851d1253d4858f9b63c533df6bcfe76a393f;hp=0000000000000000000000000000000000000000;hpb=439c154020869f0ed08094f3aeb01920312ec31a;p=lgpl%2Fargeo-commons.git 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"); + } + } +}