// Copyright (C) 2009 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.gerrit.pgm.util; import static java.util.concurrent.TimeUnit.HOURS; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.git.WorkQueue; import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.GZIPOutputStream; /** Compresses the old error logs. */ public class LogFileCompressor implements Runnable { private static final Logger log = LoggerFactory.getLogger(LogFileCompressor.class); public static class Module extends LifecycleModule { @Override protected void configure() { listener().to(Lifecycle.class); } } static class Lifecycle implements LifecycleListener { private final WorkQueue queue; private final LogFileCompressor compresser; @Inject Lifecycle(final WorkQueue queue, final LogFileCompressor compressor) { this.queue = queue; this.compresser = compressor; } @Override public void start() { queue.getDefaultQueue().scheduleAtFixedRate(compresser, 1, 24, HOURS); } @Override public void stop() { } } private final File logs_dir; @Inject LogFileCompressor(final SitePaths site) { logs_dir = resolve(site.logs_dir); } private static File resolve(final File logs_dir) { try { return logs_dir.getCanonicalFile(); } catch (IOException e) { return logs_dir.getAbsoluteFile(); } } @Override public void run() { final File[] list = logs_dir.listFiles(); if (list == null) { return; } for (final File entry : list) { if (!isLive(entry) && !isCompressed(entry) && isLogFile(entry)) { compress(entry); } } } private boolean isLive(final File entry) { final String name = entry.getName(); return name.endsWith("_log") || name.endsWith(".log") || name.endsWith(".run") || name.endsWith(".pid"); } private boolean isCompressed(final File entry) { final String name = entry.getName(); return name.endsWith(".gz") // || name.endsWith(".zip") // || name.endsWith(".bz2"); } private boolean isLogFile(final File entry) { return entry.isFile(); } private void compress(final File src) { final File dir = src.getParentFile(); final File dst = new File(dir, src.getName() + ".gz"); final File tmp = new File(dir, ".tmp." + src.getName()); try { try (InputStream in = new FileInputStream(src); FileOutputStream fo = new FileOutputStream(tmp); OutputStream out = new GZIPOutputStream(fo)) { final byte[] buf = new byte[2048]; int n; while (0 < (n = in.read(buf))) { out.write(buf, 0, n); } tmp.setReadOnly(); } if (!tmp.renameTo(dst)) { throw new IOException("Cannot rename " + tmp + " to " + dst); } src.delete(); } catch (IOException e) { log.error("Cannot compress " + src, e); tmp.delete(); } } @Override public String toString() { return "Log File Compressor"; } }