/*
 * Copyright 2014-2019 Real Logic Ltd.
 *
 * 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
 *
 * https://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 org.agrona.concurrent.errors;

import org.agrona.ErrorHandler;

import java.io.PrintStream;
import java.util.Objects;

/**
 * A logging {@link ErrorHandler} that records to a {@link DistinctErrorLog} and if the log is full then overflows
 * to a {@link PrintStream}.
 */
public class LoggingErrorHandler implements ErrorHandler
{
    private final DistinctErrorLog log;
    private final PrintStream errorOverflow;

    /**
     * Construct error handler wrapping a {@link DistinctErrorLog} with a default of {@link System#err} for the
     * {@link #errorOverflow()}.
     *
     * @param log to wrap.
     */
    public LoggingErrorHandler(final DistinctErrorLog log)
    {
        this(log, System.err);
    }

    /**
     * Construct error handler wrapping a {@link DistinctErrorLog} and {@link PrintStream} for error overflow.
     *
     * @param log           to wrap.
     * @param errorOverflow to be used if the log fills.
     */
    public LoggingErrorHandler(final DistinctErrorLog log, final PrintStream errorOverflow)
    {
        Objects.requireNonNull(log, "log");
        Objects.requireNonNull(log, "errorOverflow");

        this.log = log;
        this.errorOverflow = errorOverflow;
    }

    /**
     * The wrapped log.
     *
     * @return the wrapped log.
     */
    public DistinctErrorLog distinctErrorLog()
    {
        return log;
    }

    /**
     * The wrapped {@link PrintStream} for error log overflow when the log is full.
     *
     * @return wrapped {@link PrintStream} for error log overflow when the log is full.
     */
    public PrintStream errorOverflow()
    {
        return errorOverflow;
    }

    public void onError(final Throwable throwable)
    {
        if (!log.record(throwable))
        {
            errorOverflow.println("error Log is full, consider increasing length of error buffer");
            throwable.printStackTrace(errorOverflow);
        }
    }
}

@@ -868,16 +868,79 @@
 Stream%7D.
+ If closed then error will be sent to %7B@link #errorOverflow()%7D.
 %0A */%0Apub
@@ -996,10 +996,64 @@
 dler
-%0A%7B
+, AutoCloseable%0A%7B%0A    private volatile boolean isClosed;
 %0A   
@@ -1925,32 +1925,434 @@
 verflow;%0A    %7D%0A%0A
+    /**%0A     * Close error handler so that is does not attempt to write to underlying storage which may be unmapped.%0A     */%0A    public void close()%0A    %7B%0A        isClosed = true;%0A    %7D%0A%0A    /**%0A     * Is this %7B@link LoggingErrorHandler%7D closed.%0A     *%0A     * @return true if %7B@link #close()%7D has been called otherwise false.%0A     */%0A    public boolean isClosed()%0A    %7B%0A        return isClosed;%0A    %7D%0A%0A
     /**%0A     * T
@@ -2839,16 +2839,175 @@
      if 
+(isClosed)%0A        %7B%0A            errorOverflow.println(%22error log is closed%22);%0A            throwable.printStackTrace(errorOverflow);%0A        %7D%0A        else if 
 (!log.re
@@ -3074,17 +3074,17 @@
 (%22error 
-L
+l
 og is fu

Implement AutoCloseable for LoggingErrorHandler so that is can be closed and thus not using underlying DistinctErrorLog which may have been unmpapped.