/*
 * Copyright 2011 Google Inc.
 * 
 * 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.gwt.dev.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.util.tools.Utility;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A class that manages a persistent cache of {@link CompilationUnit} instances.
 * Writes out {@CompilationUnit} instances to a cache in a
 * background thread.
 * <p>
 * The persistent cache is implemented as a directory of log files with a date
 * timestamp. A new log file gets created each time a new PersistentUnitCache is
 * instantiated, (once per invocation of the compiler or DevMode). The design is
 * intended to support only a single PersistentUnitCache instance in the
 * compiler at a time.
 * <p>
 * As new units are compiled, the cache data is appended to a log. This allows
 * Java serialization to efficiently store references. The next time the cache
 * is started, all logs are replayed and loaded into the cache in chronological
 * order, with newer units taking precedence. A new cache file is created for
 * any newly compiled units in this session. After a threshold of a certain
 * number of files in the directory is reached
 * {@link PersistentUnitCache#CACHE_FILE_THRESHOLD} , the cache files are
 * consolidated back into a single file.
 * 
 * <p>
 * System Properties (see {@link UnitCacheFactory}).
 * 
 * <ul>
 * <li>gwt.persistentunitcache : enables the persistent cache (eventually will
 * be default)</li>
 * <li>gwt.persistentunitcachedir=<dir>: sets or overrides the cache directory</li>
 * </ul>
 * 
 * <p>
 * Known Issues:
 * 
 * <ul>
 * <li>This design uses an eager cache to load every unit in the cache on the
 * first reference to find() or add(). When the cache is large (10000 units), it
 * uses lots of heap and takes 5-10 seconds. Once the PersistentUnitCache is
 * created, it starts eagerly loading the cache in a background thread).</li>
 * 
 * <li>Although units logged to disk with the same resource path are eventually
 * cleaned up, the most recently compiled unit stays in the cache forever. This
 * means that stale units that are no longer referenced will never be purged,
 * unless by some external action (e.g. ant clean).</li>
 * 
 * <li>Unless ant builds are made aware of the cache directory, the cache will
 * persist if a user does an ant clean.</li>
 * </ul>
 * 
 */
class PersistentUnitCache extends MemoryUnitCache {
  /**
   * A thread used when the cache is instantiated to load up cached units from
   * the persistent store in the background. The
   * {@link UnitCacheFactory#addUnit(CompilationUnit)} and
   * {@link UnitCacheFactory#findUnit(String)} methods block if invoked before
   * this thread finishes.
   */
  private class UnitCacheMapLoader extends Thread {
    private final CountDownLatch loadCompleteLatch = new CountDownLatch(1);
    private final TreeLogger logger;

    public UnitCacheMapLoader(TreeLogger logger) {
      this.logger = logger;
      setDaemon(true);
      setName("UnitCacheLoader");
      setPriority(Thread.NORM_PRIORITY);
    }

    public void await() {
      try {
        loadCompleteLatch.await();
      } catch (InterruptedException ex) {
        logger.log(TreeLogger.ERROR, "Interrupted waiting for PersistentUnitCache to load.", ex);
      }
    }

    @Override
    public void run() {
      try {
        loadUnitMap(logger);
      } finally {
        loadCompleteLatch.countDown();
        if (logger.isLoggable(TreeLogger.TRACE)) {
          logger
              .log(TreeLogger.TRACE, "Loaded " + unitMap.size() + " units from persistent store.");
        }
      }
    }
  }

  /**
   * Used to pass messages to the unitWriteThread.
   */
  private static class UnitWriteMessage {
    private static final UnitWriteMessage DELETE_OLD_CACHE_FILES = new UnitWriteMessage();
    private static final UnitWriteMessage SHUTDOWN_THREAD = new UnitWriteMessage();
    private final UnitCacheEntry unitCacheEntry;

    public UnitWriteMessage() {
      unitCacheEntry = null;
    }

    public UnitWriteMessage(UnitCacheEntry unitCacheEntry) {
      this.unitCacheEntry = unitCacheEntry;
    }
  }

  /**
   * Thread that reads units from a queue and writes out to a cache file for
   * this session.
   */
  private class UnitWriter extends Thread {
    private final CountDownLatch shutDownLatch = new CountDownLatch(1);
    private final TreeLogger logger;
    private boolean errorLogged = false;
    private Thread shutdownHook = new Thread() {
      @Override
      public void run() {
        try {
          doShutdown();
        } catch (InterruptedException ex) {
          // ignore
        }
      }
    };

    public UnitWriter(TreeLogger logger) {
      this.logger = logger;
      setDaemon(true);
      setName("UnitWriteThread");
      setPriority(Thread.MIN_PRIORITY);

      Runtime.getRuntime().addShutdownHook(shutdownHook);
    }

    @Override
    public void run() {
      logger.log(TreeLogger.TRACE, "Starting UnitWriteThread.");

      FileOutputStream fstream = null;
      BufferedOutputStream bstream = null;
      ObjectOutputStream stream = null;
      try {
        fstream = new FileOutputStream(currentCacheFile);
        bstream = new BufferedOutputStream(fstream);
        stream = new ObjectOutputStream(bstream);
      } catch (IOException ex) {
        logger.log(TreeLogger.ERROR, "Error creating cache " + currentCacheFile
            + ". Disabling cache.", ex);
      }
      int recentUnitsWritten = 0;
      int totalUnitsWritten = 0;
      try {
        while (true) {
          UnitWriteMessage msg = null;
          try {
            msg = unitWriteQueue.take();
          } catch (InterruptedException e) {
            // Allow shutdown to interrupt
            break;
          }
          if (stream == null) {
            // if there is no output stream, just ignore the unit
            continue;
          }

          try {
            if (msg != null) {
              if (msg == UnitWriteMessage.DELETE_OLD_CACHE_FILES) {
                if (logger.isLoggable(TreeLogger.TRACE)) {
                  logger.log(TreeLogger.TRACE, "Wrote " + recentUnitsWritten
                      + " units to persistent cache.");
                }
                recentUnitsWritten = 0;
                deleteOldCacheFiles(logger, currentCacheFile);
              } else if (msg == UnitWriteMessage.SHUTDOWN_THREAD) {
                stream.flush();
                assert unitWriteQueue.size() == 0;
                break;
              } else {
                assert msg.unitCacheEntry.getOrigin() != UnitOrigin.ARCHIVE;
                CompilationUnit unit = msg.unitCacheEntry.getUnit();
                assert unit != null;
                stream.writeObject(unit);
                recentUnitsWritten++;
                totalUnitsWritten++;
              }
            }

            if (unitWriteQueue.isEmpty()) {
              stream.flush();
            }
          } catch (IOException ex) {
            if (!errorLogged) {
              errorLogged = true;
              if (logger.isLoggable(TreeLogger.TRACE)) {
                logger.log(TreeLogger.TRACE, "Error saving unit to file: "
                    + currentCacheFile.getAbsolutePath(), ex);
              }
            }
          }
        }
      } finally {
        Utility.close(stream);
        // Paranoia - close all streams
        Utility.close(bstream);
        Utility.close(fstream);
        if (totalUnitsWritten == 0) {
          // Remove useless empty output.
          currentCacheFile.delete();
        }
        shutDownLatch.countDown();
        logger.log(TreeLogger.TRACE, "Shutting down PersistentUnitCache thread");
      }
    }

    /**
     * Shutdown the thread and wait for it.
     */
    private void doShutdown() throws InterruptedException {
      // force the shutdown to finish after 5 seconds
      unitWriteQueue.add(UnitWriteMessage.SHUTDOWN_THREAD);
      // wait for shutdown
      shutDownLatch.await(5000, TimeUnit.MILLISECONDS);
      try {
        Runtime.getRuntime().removeShutdownHook(shutdownHook);
      } catch (IllegalStateException ex) {
        // ignore.
      }
    }
  }

  /**
   * Common prefix for creating directories and cache files.
   */
  static final String UNIT_CACHE_PREFIX = "gwt-unitCache";

  static final String CACHE_FILE_PREFIX = UNIT_CACHE_PREFIX + "-";

  /**
   * If there are more than this many files in the cache, clean up the old
   * files.
   */
  static final int CACHE_FILE_THRESHOLD = 10;

  /**
   * Used for communication to the unit write thread.
   */
  private final BlockingQueue<UnitWriteMessage> unitWriteQueue =
      new LinkedBlockingQueue<UnitWriteMessage>();
  private final AtomicInteger addCount = new AtomicInteger(0);
  private final UnitCacheMapLoader unitCacheMapLoader;
  private final UnitWriter unitWriter;
  private boolean cleanupHasRun = false;

  /**
   * A directory that ideally persists between invocations.
   */
  private final File cacheDirectory;

  /**
   * Cache log file currently being written to.
   */
  private File currentCacheFile;

  PersistentUnitCache(TreeLogger logger, File cacheDir) throws UnableToCompleteException {
    assert cacheDir != null;

    this.cacheDirectory = new File(cacheDir, UNIT_CACHE_PREFIX);
    if (logger.isLoggable(TreeLogger.TRACE)) {
      logger.log(TreeLogger.TRACE, "Persistent unit cache dir set to: "
          + this.cacheDirectory.getAbsolutePath());
    }

    if (!cacheDirectory.isDirectory() && !cacheDirectory.mkdirs()) {
      logger.log(TreeLogger.WARN, "Unable to initialize cache. Couldn't create directory "
          + cacheDirectory.getAbsolutePath() + ".");
      throw new UnableToCompleteException();
    }

    long timestamp = System.currentTimeMillis();
    do {
      currentCacheFile =
          new File(cacheDirectory, CACHE_FILE_PREFIX + String.format("%016X", timestamp++));
    } while (currentCacheFile.exists());

    // This isn't 100% reliable if multiple processes are in contention
    try {
      currentCacheFile.createNewFile();
    } catch (IOException ex) {
      logger.log(TreeLogger.WARN, "Unable to create new cache log file "
          + currentCacheFile.getAbsolutePath() + ".", ex);
      throw new UnableToCompleteException();
    }

    unitCacheMapLoader = new UnitCacheMapLoader(logger);
    unitCacheMapLoader.start();
    unitWriter = new UnitWriter(logger);
    unitWriter.start();
  }

  /**
   * Enqueue a unit to be written by the background thread.
   */
  @Override
  public void add(CompilationUnit newUnit) {
    unitCacheMapLoader.await();
    super.add(newUnit);
    UnitCacheEntry entry = unitMap.get(newUnit.getResourcePath());
    addCount.getAndIncrement();
    unitWriteQueue.add(new UnitWriteMessage(entry));
  }

  /**
   * Cleans up old cache files in the directory, migrating everything previously
   * loaded in them to the current cache file.
   * 
   * Normally, only newly compiled units are written to the current log, but
   * when it is time to cleanup, valid units from older log files need to be
   * re-written.
   */
  @Override
  public void cleanup(TreeLogger logger) {
    if (logger.isLoggable(TreeLogger.TRACE)) {
      logger.log(TreeLogger.TRACE, "Added " + addCount.intValue() + " units to persistent cache.");
    }
    addCount.set(0);

    if (cleanupHasRun) {
      return;
    }

    cleanupHasRun = true;
    unitCacheMapLoader.await();
    File[] cacheFiles = getCacheFiles();

    if (cacheFiles.length < CACHE_FILE_THRESHOLD) {
      return;
    }

    /*
     * Resend all units read in from the in-memory cache to the writer thread.
     * They will be re-written out and the old cache files removed.
     */
    synchronized (unitMap) {
      for (UnitCacheEntry unitCacheEntry : unitMap.values()) {
        if (unitCacheEntry.getOrigin() == UnitOrigin.PERSISTENT) {
          unitWriteQueue.add(new UnitWriteMessage(unitCacheEntry));
        }
      }
    }
    unitWriteQueue.add(UnitWriteMessage.DELETE_OLD_CACHE_FILES);
  }

  @Override
  public CompilationUnit find(ContentId contentId) {
    unitCacheMapLoader.await();
    return super.find(contentId);
  }

  @Override
  public CompilationUnit find(String resourcePath) {
    unitCacheMapLoader.await();
    return super.find(resourcePath);
  }

  /**
   * Delete all cache files in the directory except for the currently open file.
   * 
   * @param current Specifies the currently open cache file which will not be
   *          deleted.
   */
  void deleteOldCacheFiles(TreeLogger logger, File current) {
    assert current != null;

    SpeedTracerLogger.Event deleteEvent = SpeedTracerLogger.start(DevModeEventType.DELETE_CACHE);
    File[] filesToDelete = getCacheFiles();
    if (filesToDelete == null) {
      return;
    }
    if (logger.isLoggable(TreeLogger.INFO)) {
      logger.log(TreeLogger.TRACE, "Purging cache files from " + cacheDirectory);
    }
    for (File toDelete : filesToDelete) {
      if (!current.equals(toDelete)) {
        toDelete.delete();
      }
    }
    deleteEvent.end();
  }

  /**
   * Finds all files matching a pattern in the cache directory.
   * 
   * @return an array of sorted filenames. The file name pattern is such that
   *         sorting them alphabetically also sorts the files by age.
   */
  File[] getCacheFiles() {
    if (cacheDirectory.isDirectory()) {
      File[] files = cacheDirectory.listFiles();
      List<File> cacheFiles = new ArrayList<File>();
      for (File file : files) {
        if (file.getName().startsWith(CACHE_FILE_PREFIX)) {
          cacheFiles.add(file);
        }
      }
      File[] retFiles = cacheFiles.toArray(new File[cacheFiles.size()]);
      Arrays.sort(retFiles);
      return retFiles;
    }
    return new File[0];
  }

  /**
   * For Unit testing - shutdown the persistent cache.
   */
  void shutdown() throws InterruptedException {
    unitWriter.doShutdown();
  }

  /**
   * Load everything cached on disk into memory.
   */
  private void loadUnitMap(TreeLogger logger) {
    Event loadPersistentUnitEvent =
        SpeedTracerLogger.start(DevModeEventType.LOAD_PERSISTENT_UNIT_CACHE);
    if (logger.isLoggable(TreeLogger.TRACE)) {
      logger.log(TreeLogger.TRACE, "Looking for previously cached Compilation Units in "
          + cacheDirectory.getAbsolutePath());
    }
    try {
      if (cacheDirectory.isDirectory() && cacheDirectory.canRead()) {
        File[] files = getCacheFiles();
        for (File cacheFile : files) {
          FileInputStream fis = null;
          BufferedInputStream bis = null;
          ObjectInputStream inputStream = null;
          if (cacheFile.equals(currentCacheFile)) {
            continue;
          }
          boolean deleteCacheFile = false;
          try {
            fis = new FileInputStream(cacheFile);
            bis = new BufferedInputStream(fis);
            /*
             * It is possible for the next call to throw an exception, leaving
             * inputStream null and fis still live.
             */
            inputStream = new ObjectInputStream(bis);
            while (true) {
              CachedCompilationUnit unit = (CachedCompilationUnit) inputStream.readObject();
              if (unit == null) {
                break;
              }
              if (GwtAstBuilder.ENABLED) {
                if (unit.getTypesSerializedVersion() != GwtAstBuilder.getSerializationVersion()) {
                  continue;
                }
              }
              UnitCacheEntry entry = new UnitCacheEntry(unit, UnitOrigin.PERSISTENT);
              UnitCacheEntry oldEntry = unitMap.get(unit.getResourcePath());
              if (oldEntry != null && unit.getLastModified() > oldEntry.getUnit().getLastModified()) {
                super.remove(oldEntry.getUnit());
                unitMap.put(unit.getResourcePath(), entry);
                unitMapByContentId.put(unit.getContentId(), entry);
              } else if (oldEntry == null) {
                unitMap.put(unit.getResourcePath(), entry);
                unitMapByContentId.put(unit.getContentId(), entry);
              }
            }
          } catch (EOFException ex) {
            // Go on to the next file.
          } catch (IOException ex) {
            deleteCacheFile = true;
            if (logger.isLoggable(TreeLogger.TRACE)) {
              logger.log(TreeLogger.TRACE, "Ignoring and deleting cache log "
                  + cacheFile.getAbsolutePath() + " due to read error.", ex);
            }
          } catch (ClassNotFoundException ex) {
            deleteCacheFile = true;
            if (logger.isLoggable(TreeLogger.TRACE)) {
              logger.log(TreeLogger.TRACE, "Ignoring and deleting cache log "
                  + cacheFile.getAbsolutePath() + " due to deserialization error.", ex);
            }
          } finally {
            Utility.close(inputStream);
            Utility.close(bis);
            Utility.close(fis);
          }
          if (deleteCacheFile) {
            cacheFile.delete();
          } else {
            if (logger.isLoggable(TreeLogger.TRACE)) {
              logger.log(TreeLogger.TRACE, cacheFile.getName() + ": Load complete");
            }
          }
        }
      } else {
        logger
            .log(TreeLogger.TRACE,
                "Starting with empty Cache: CompilationUnit cache directory does not exist or is not readable.");
      }
    } finally {
      loadPersistentUnitEvent.end();
    }
  }
}
