summaryrefslogtreecommitdiffstats
path: root/logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java
diff options
context:
space:
mode:
Diffstat (limited to 'logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java')
-rw-r--r--logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java147
1 files changed, 147 insertions, 0 deletions
diff --git a/logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java b/logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java
new file mode 100644
index 00000000000..fb78e8243c3
--- /dev/null
+++ b/logserver/src/main/java/com/yahoo/logserver/handlers/archive/LogWriter.java
@@ -0,0 +1,147 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.logserver.handlers.archive;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.logging.Logger;
+
+import com.yahoo.log.LogLevel;
+
+/**
+ * This class is not thread-safe.
+ *
+ *
+ * @author <a href="mailto:borud@yahoo-inc.com">Bjorn Borud</a>
+ */
+public class LogWriter extends Writer
+{
+ private static final Logger log = Logger.getLogger(LogWriter.class.getName());
+
+ private long bytesWritten = 0;
+ private int generation = 0;
+ private int maxSize = 20 * (1024*1024);
+ private final int resumeLimit = 95;
+ private final int resumeLimitSize = (maxSize * resumeLimit / 100);
+ private File currentFile;
+ private Writer writer;
+ private final String prefix;
+
+ public LogWriter (String prefix, int maxSize) throws IOException {
+ this.prefix = prefix;
+ this.maxSize = maxSize;
+ writer = nextWriter();
+ }
+
+ /**
+ * This is called when we want to rotate the output file to
+ * start writing the next file. There are two scenarios when
+ * we do this:
+ *
+ * <UL>
+ * <LI> initial case, when we have no file
+ * <LI> when we have filled the file and want to rotate it
+ * </UL>
+ *
+ */
+ private Writer nextWriter () throws IOException {
+
+ if (writer != null) {
+ writer.close();
+ }
+
+ int maxAttempts = 1000;
+ while (maxAttempts-- > 0) {
+ String name = prefix + "-" + generation++;
+ File f = new File(name);
+
+ // make sure directory exists
+ File dir = f.getParentFile();
+ if (! dir.exists()) {
+ dir.mkdirs();
+ }
+
+ // if compressed version exists we skip it
+ if ((new File(name + ".gz").exists())
+ || (new File(name + ".bz2").exists())) {
+ continue;
+ }
+
+ // if file does not exist we have a winner
+ if (! f.exists()) {
+ log.log(LogLevel.DEBUG, "nextWriter, new file: " + name);
+ currentFile = f;
+ bytesWritten = 0;
+ return new FileWriter(f, true);
+ }
+
+ // just skip over directories for now
+ if (! f.isFile()) {
+ log.fine("nextWriter, " + name + " is a directory, skipping");
+ continue;
+ }
+
+ // if the size is < resumeSizeLimit then we open it
+ if (f.length() < resumeLimitSize) {
+ log.fine("nextWriter, resuming " + name + ", length was " + f.length());
+ currentFile = f;
+ bytesWritten = f.length();
+ return new FileWriter(f, true);
+ } else {
+
+ log.fine("nextWriter, not resuming " + name
+ + " because it is bigger than "
+ + resumeLimit
+ + " percent of max");
+ }
+ }
+
+ throw new RuntimeException("Unable to create next log file");
+ }
+
+ /**
+ * Note that this method should not be used directly since
+ * that would circumvent rotation when it grows past its
+ * maximum size. use the one that takes String instead.
+ *
+ * <P>
+ * <em>
+ * (This is a class which is only used internally anyway)
+ * </em>
+ */
+ public void write (char[] cbuff, int offset, int len) throws IOException {
+ throw new RuntimeException("This method should not be used");
+ }
+
+ public void write(String str) throws IOException {
+ if (writer == null) {
+ writer = nextWriter();
+ }
+
+ bytesWritten += str.length();
+ writer.write(str, 0, str.length());
+
+ if (bytesWritten >= maxSize) {
+ log.fine("logfile '"
+ + currentFile.getAbsolutePath()
+ + "' full, rotating");
+ writer = nextWriter();
+ }
+ }
+
+
+ public void flush() throws IOException{
+ if (writer != null) {
+ writer.flush();
+ }
+ }
+
+ public void close() throws IOException {
+ flush();
+ if (writer != null) {
+ writer.close();
+ writer = null;
+ }
+ }
+}