/*
 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package jdk.nashorn.internal.codegen;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.AccessController;
import java.security.MessageDigest;
import java.security.PrivilegedAction;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.options.Options;

/**
 * <p>Static utility that encapsulates persistence of type information for functions compiled with optimistic
 * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized,
 * the type information for deoptimization is stored in a cache file. If the same function is compiled in a
 * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system
 * to skip a lot of intermediate recompilations and immediately emit a version of the code that has its
 * optimistic types at (or near) the steady state.
 * </p><p>
 * Normally, the type info persistence feature is disabled. When the {@code nashorn.typeInfo.maxFiles} system
 * property is specified with a value greater than 0, it is enabled and operates in an operating-system
 * specific per-user cache directory. You can override the directory by specifying it in the
 * {@code nashorn.typeInfo.cacheDir} directory. The maximum number of files is softly enforced by a task that
 * cleans up the directory periodically on a separate thread. It is run after some delay after a new file is
 * added to the cache. The default delay is 20 seconds, and can be set using the
 * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word
 * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is
 * allowed to grow without limits.
 * </p>
 */
public final class OptimisticTypesPersistence {
    // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is
    // dependent on the application; setting it to e.g. 20000 is probably good enough for most uses and will
    // usually cap the cache directory to about 80MB presuming a 4kB filesystem allocation unit. There is one
    // file per JavaScript function.
    private static final int DEFAULT_MAX_FILES = 0;
    // Constants for signifying that the cache should not be limited
    private static final int UNLIMITED_FILES = -1;
    // Maximum number of files that should be cached on disk. The maximum will be softly enforced.
    private static final int MAX_FILES = getMaxFiles();
    // Number of seconds to wait between adding a new file to the cache and running a cleanup process
    private static final int DEFAULT_CLEANUP_DELAY = 20;
    private static final int CLEANUP_DELAY = Math.max(0, Options.getIntProperty(
            "nashorn.typeInfo.cleanupDelaySeconds", DEFAULT_CLEANUP_DELAY));
    // The name of the default subdirectory within the system cache directory where we store type info.
    private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo";
    // The directory where we cache type info
    private static final File baseCacheDir = createBaseCacheDir();
    private static final File cacheDir = createCacheDir(baseCacheDir);
    // In-process locks to make sure we don't have a cross-thread race condition manipulating any file.
    private static final Object[] locks = cacheDir == null ? null : createLockArray();
    // Only report one read/write error every minute
    private static final long ERROR_REPORT_THRESHOLD = 60000L;

    private static volatile long lastReportedError;
    private static final AtomicBoolean scheduledCleanup;
    private static final Timer cleanupTimer;
    static {
        if (baseCacheDir == null || MAX_FILES == UNLIMITED_FILES) {
            scheduledCleanup = null;
            cleanupTimer = null;
        } else {
            scheduledCleanup = new AtomicBoolean();
            cleanupTimer = new Timer(true);
        }
    }
    /**
     * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed
     * to {@link #load(Object)} and {@link #store(Object, Map)} methods.
     * @param source the source where the function comes from
     * @param functionId the unique ID number of the function within the source
     * @param paramTypes the types of the function parameters (as persistence is per parameter type
     * specialization).
     * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
     */
    public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
        if(cacheDir == null) {
            return null;
        }
        final StringBuilder b = new StringBuilder(48);
        // Base64-encode the digest of the source, and append the function id.
        b.append(source.getDigest()).append('-').append(functionId);
        // Finally, if this is a parameter-type specialized version of the function, add the parameter types
        // to the file name.
        if(paramTypes != null && paramTypes.length > 0) {
            b.append('-');
            for(final Type t: paramTypes) {
                b.append(Type.getShortSignatureDescriptor(t));
            }
        }
        return new LocationDescriptor(new File(cacheDir, b.toString()));
    }

    private static final class LocationDescriptor {
        private final File file;

        LocationDescriptor(final File file) {
            this.file = file;
        }
    }


    /**
     * Stores the map of optimistic types for a given function.
     * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
     * {@link #getLocationDescriptor(Source, int, Type[])}.
     * @param optimisticTypes the map of optimistic types.
     */
    @SuppressWarnings("resource")
    public static void store(final Object locationDescriptor, final Map<Integer, Type> optimisticTypes) {
        if(locationDescriptor == null || optimisticTypes.isEmpty()) {
            return;
        }
        final File file = ((LocationDescriptor)locationDescriptor).file;

        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            @Override
            public Void run() {
                synchronized(getFileLock(file)) {
                    if (!file.exists()) {
                        // If the file already exists, we aren't increasing the number of cached files, so
                        // don't schedule cleanup.
                        scheduleCleanup();
                    }
                    try (final FileOutputStream out = new FileOutputStream(file)) {
                        out.getChannel().lock(); // lock exclusive
                        final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out));
                        Type.writeTypeMap(optimisticTypes, dout);
                        dout.flush();
                    } catch(final Exception e) {
                        reportError("write", file, e);
                    }
                }
                return null;
            }
        });
    }

    /**
     * Loads the map of optimistic types for a given function.
     * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
     * {@link #getLocationDescriptor(Source, int, Type[])}.
     * @return the map of optimistic types, or null if persisted type information could not be retrieved.
     */
    @SuppressWarnings("resource")
    public static Map<Integer, Type> load(final Object locationDescriptor) {
        if (locationDescriptor == null) {
            return null;
        }
        final File file = ((LocationDescriptor)locationDescriptor).file;
        return AccessController.doPrivileged(new PrivilegedAction<Map<Integer, Type>>() {
            @Override
            public Map<Integer, Type> run() {
                try {
                    if(!file.isFile()) {
                        return null;
                    }
                    synchronized(getFileLock(file)) {
                        try (final FileInputStream in = new FileInputStream(file)) {
                            in.getChannel().lock(0, Long.MAX_VALUE, true); // lock shared
                            final DataInputStream din = new DataInputStream(new BufferedInputStream(in));
                            return Type.readTypeMap(din);
                        }
                    }
                } catch (final Exception e) {
                    reportError("read", file, e);
                    return null;
                }
            }
        });
    }

    private static void reportError(final String msg, final File file, final Exception e) {
        final long now = System.currentTimeMillis();
        if(now - lastReportedError > ERROR_REPORT_THRESHOLD) {
            reportError(String.format("Failed to %s %s", msg, file), e);
            lastReportedError = now;
        }
    }

    /**
     * Logs an error message with warning severity (reasoning being that we're reporting an error that'll disable the
     * type info cache, but it's only logged as a warning because that doesn't prevent Nashorn from running, it just
     * disables a performance-enhancing cache).
     * @param msg the message to log
     * @param e the exception that represents the error.
     */
    private static void reportError(final String msg, final Exception e) {
        getLogger().warning(msg, "\n", exceptionToString(e));
    }

    /**
     * A helper that prints an exception stack trace into a string. We have to do this as if we just pass the exception
     * to {@link DebugLogger#warning(Object...)}, it will only log the exception message and not the stack, making
     * problems harder to diagnose.
     * @param e the exception
     * @return the string representation of {@link Exception#printStackTrace()} output.
     */
    private static String exceptionToString(final Exception e) {
        final StringWriter sw = new StringWriter();
        final PrintWriter pw = new PrintWriter(sw, false);
        e.printStackTrace(pw);
        pw.flush();
        return sw.toString();
    }

    private static File createBaseCacheDir() {
        if(MAX_FILES == 0 || Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
            return null;
        }
        try {
            return createBaseCacheDirPrivileged();
        } catch(final Exception e) {
            reportError("Failed to create cache dir", e);
            return null;
        }
    }

    private static File createBaseCacheDirPrivileged() {
        return AccessController.doPrivileged(new PrivilegedAction<File>() {
            @Override
            public File run() {
                final String explicitDir = System.getProperty("nashorn.typeInfo.cacheDir");
                final File dir;
                if(explicitDir != null) {
                    dir = new File(explicitDir);
                } else {
                    // When no directory is explicitly specified, get an operating system specific cache
                    // directory, and create "com.oracle.java.NashornTypeInfo" in it.
                    final File systemCacheDir = getSystemCacheDir();
                    dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME);
                    if (isSymbolicLink(dir)) {
                        return null;
                    }
                }
                return dir;
            }
        });
    }

    private static File createCacheDir(final File baseDir) {
        if (baseDir == null) {
            return null;
        }
        try {
            return createCacheDirPrivileged(baseDir);
        } catch(final Exception e) {
            reportError("Failed to create cache dir", e);
            return null;
        }
    }

    private static File createCacheDirPrivileged(final File baseDir) {
        return AccessController.doPrivileged(new PrivilegedAction<File>() {
            @Override
            public File run() {
                final String versionDirName;
                try {
                    versionDirName = getVersionDirName();
                } catch(final Exception e) {
                    reportError("Failed to calculate version dir name", e);
                    return null;
                }
                final File versionDir = new File(baseDir, versionDirName);
                if (isSymbolicLink(versionDir)) {
                    return null;
                }
                versionDir.mkdirs();
                if (versionDir.isDirectory()) {
                    getLogger().info("Optimistic type persistence directory is " + versionDir);
                    return versionDir;
                }
                getLogger().warning("Could not create optimistic type persistence directory " + versionDir);
                return null;
            }
        });
    }

    /**
     * Returns an operating system specific root directory for cache files.
     * @return an operating system specific root directory for cache files.
     */
    private static File getSystemCacheDir() {
        final String os = System.getProperty("os.name", "generic");
        if("Mac OS X".equals(os)) {
            // Mac OS X stores caches in ~/Library/Caches
            return new File(new File(System.getProperty("user.home"), "Library"), "Caches");
        } else if(os.startsWith("Windows")) {
            // On Windows, temp directory is the best approximation of a cache directory, as its contents
            // persist across reboots and various cleanup utilities know about it. java.io.tmpdir normally
            // points to a user-specific temp directory, %HOME%\LocalSettings\Temp.
            return new File(System.getProperty("java.io.tmpdir"));
        } else {
            // In other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache"
            return new File(System.getProperty("user.home"), ".cache");
        }
    }

    /**
     * In order to ensure that changes in Nashorn code don't cause corruption in the data, we'll create a
     * per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath
     * for nashorn is local directory (e.g. during development), this will create the string "dev-" followed by the
     * timestamp of the most recent .class file.
     *
     * @return digest of currently running nashorn
     * @throws Exception if digest could not be created
     */
    public static String getVersionDirName() throws Exception {
        // NOTE: getResource("") won't work if the JAR file doesn't have directory entries (and JAR files in JDK distro
        // don't, or at least it's a bad idea counting on it). Alternatively, we could've tried
        // getResource("OptimisticTypesPersistence.class") but behavior of getResource with regard to its willingness
        // to hand out URLs to .class files is also unspecified. Therefore, the most robust way to obtain an URL to our
        // package is to have a small non-class anchor file and start out from its URL.
        final URL url = OptimisticTypesPersistence.class.getResource("anchor.properties");
        final String protocol = url.getProtocol();
        if (protocol.equals("jar")) {
            // Normal deployment: nashorn.jar
            final String jarUrlFile = url.getFile();
            final String filePath = jarUrlFile.substring(0, jarUrlFile.indexOf('!'));
            final URL file = new URL(filePath);
            try (final InputStream in = file.openStream()) {
                final byte[] buf = new byte[128*1024];
                final MessageDigest digest = MessageDigest.getInstance("SHA-1");
                for(;;) {
                    final int l = in.read(buf);
                    if(l == -1) {
                        return Base64.getUrlEncoder().withoutPadding().encodeToString(digest.digest());
                    }
                    digest.update(buf, 0, l);
                }
            }
        } else if(protocol.equals("file")) {
            // Development
            final String fileStr = url.getFile();
            final String className = OptimisticTypesPersistence.class.getName();
            final int packageNameLen = className.lastIndexOf('.');
            final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1);
            final File dir = new File(dirStr);
            return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(
                    dir, 0L)));
        } else {
            throw new AssertionError();
        }
    }

    private static long getLastModifiedClassFile(final File dir, final long max) {
        long currentMax = max;
        for(final File f: dir.listFiles()) {
            if(f.getName().endsWith(".class")) {
                final long lastModified = f.lastModified();
                if (lastModified > currentMax) {
                    currentMax = lastModified;
                }
            } else if (f.isDirectory()) {
                final long lastModified = getLastModifiedClassFile(f, currentMax);
                if (lastModified > currentMax) {
                    currentMax = lastModified;
                }
            }
        }
        return currentMax;
    }

    /**
     * Returns true if the specified file is a symbolic link, and also logs a warning if it is.
     * @param file the file
     * @return true if file is a symbolic link, false otherwise.
     */
    private static boolean isSymbolicLink(final File file) {
        if (Files.isSymbolicLink(file.toPath())) {
            getLogger().warning("Directory " + file + " is a symlink");
            return true;
        }
        return false;
    }

    private static Object[] createLockArray() {
        final Object[] lockArray = new Object[Runtime.getRuntime().availableProcessors() * 2];
        for (int i = 0; i < lockArray.length; ++i) {
            lockArray[i] = new Object();
        }
        return lockArray;
    }

    private static Object getFileLock(final File file) {
        return locks[(file.hashCode() & Integer.MAX_VALUE) % locks.length];
    }

    private static DebugLogger getLogger() {
        try {
            return Context.getContext().getLogger(RecompilableScriptFunctionData.class);
        } catch (final Exception e) {
            e.printStackTrace();
            return DebugLogger.DISABLED_LOGGER;
        }
    }

    private static void scheduleCleanup() {
        if (MAX_FILES != UNLIMITED_FILES && scheduledCleanup.compareAndSet(false, true)) {
            cleanupTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    scheduledCleanup.set(false);
                    try {
                        doCleanup();
                    } catch (final IOException e) {
                        // Ignore it. While this is unfortunate, we don't have good facility for reporting
                        // this, as we're running in a thread that has no access to Context, so we can't grab
                        // a DebugLogger.
                    }
                }
            }, TimeUnit.SECONDS.toMillis(CLEANUP_DELAY));
        }
    }

    private static void doCleanup() throws IOException {
        final Path[] files = getAllRegularFilesInLastModifiedOrder();
        final int nFiles = files.length;
        final int filesToDelete = Math.max(0, nFiles - MAX_FILES);
        int filesDeleted = 0;
        for (int i = 0; i < nFiles && filesDeleted < filesToDelete; ++i) {
            try {
                Files.deleteIfExists(files[i]);
                // Even if it didn't exist, we increment filesDeleted; it existed a moment earlier; something
                // else deleted it for us; that's okay with us.
                filesDeleted++;
            } catch (final Exception e) {
                // does not increase filesDeleted
            }
            files[i] = null; // gc eligible
        }
    }

    private static Path[] getAllRegularFilesInLastModifiedOrder() throws IOException {
        try (final Stream<Path> filesStream = Files.walk(baseCacheDir.toPath())) {
            // TODO: rewrite below once we can use JDK8 syntactic constructs
            return filesStream
            .filter(new Predicate<Path>() {
                @Override
                public boolean test(final Path path) {
                    return !Files.isDirectory(path);
                }
            })
            .map(new Function<Path, PathAndTime>() {
                @Override
                public PathAndTime apply(final Path path) {
                    return new PathAndTime(path);
                }
            })
            .sorted()
            .map(new Function<PathAndTime, Path>() {
                @Override
                public Path apply(final PathAndTime pathAndTime) {
                    return pathAndTime.path;
                }
            })
            .toArray(new IntFunction<Path[]>() { // Replace with Path::new
                @Override
                public Path[] apply(final int length) {
                    return new Path[length];
                }
            });
        }
    }

    private static class PathAndTime implements Comparable<PathAndTime> {
        private final Path path;
        private final long time;

        PathAndTime(final Path path) {
            this.path = path;
            this.time = getTime(path);
        }

        @Override
        public int compareTo(final PathAndTime other) {
            return Long.compare(time, other.time);
        }

        private static long getTime(final Path path) {
            try {
                return Files.getLastModifiedTime(path).toMillis();
            } catch (final IOException e) {
                // All files for which we can't retrieve the last modified date will be considered oldest.
                return -1L;
            }
        }
    }

    private static int getMaxFiles() {
        final String str = Options.getStringProperty("nashorn.typeInfo.maxFiles", null);
        if (str == null) {
            return DEFAULT_MAX_FILES;
        } else if ("unlimited".equals(str)) {
            return UNLIMITED_FILES;
        }
        return Math.max(0, Integer.parseInt(str));
    }
}
