/*
 * Copyright (C) 2009, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.lib;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.internal.WorkQueue;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Cache of active {@link org.eclipse.jgit.lib.Repository} instances.
 */
public class RepositoryCache {
	private static final Logger LOG = LoggerFactory
			.getLogger(RepositoryCache.class);

	private static final RepositoryCache cache = new RepositoryCache();

	/**
	 * Open an existing repository, reusing a cached instance if possible.
	 * <p>
	 * When done with the repository, the caller must call
	 * {@link org.eclipse.jgit.lib.Repository#close()} to decrement the
	 * repository's usage counter.
	 *
	 * @param location
	 *            where the local repository is. Typically a
	 *            {@link org.eclipse.jgit.lib.RepositoryCache.FileKey}.
	 * @return the repository instance requested; caller must close when done.
	 * @throws java.io.IOException
	 *             the repository could not be read (likely its core.version
	 *             property is not supported).
	 * @throws org.eclipse.jgit.errors.RepositoryNotFoundException
	 *             there is no repository at the given location.
	 */
	public static Repository open(Key location) throws IOException,
			RepositoryNotFoundException {
		return open(location, true);
	}

	/**
	 * Open a repository, reusing a cached instance if possible.
	 * <p>
	 * When done with the repository, the caller must call
	 * {@link org.eclipse.jgit.lib.Repository#close()} to decrement the
	 * repository's usage counter.
	 *
	 * @param location
	 *            where the local repository is. Typically a
	 *            {@link org.eclipse.jgit.lib.RepositoryCache.FileKey}.
	 * @param mustExist
	 *            If true, and the repository is not found, throws {@code
	 *            RepositoryNotFoundException}. If false, a repository instance
	 *            is created and registered anyway.
	 * @return the repository instance requested; caller must close when done.
	 * @throws java.io.IOException
	 *             the repository could not be read (likely its core.version
	 *             property is not supported).
	 * @throws RepositoryNotFoundException
	 *             There is no repository at the given location, only thrown if
	 *             {@code mustExist} is true.
	 */
	public static Repository open(Key location, boolean mustExist)
			throws IOException {
		return cache.openRepository(location, mustExist);
	}

	/**
	 * Register one repository into the cache.
	 * <p>
	 * During registration the cache automatically increments the usage counter,
	 * permitting it to retain the reference. A
	 * {@link org.eclipse.jgit.lib.RepositoryCache.FileKey} for the repository's
	 * {@link org.eclipse.jgit.lib.Repository#getDirectory()} is used to index
	 * the repository in the cache.
	 * <p>
	 * If another repository already is registered in the cache at this
	 * location, the other instance is closed.
	 *
	 * @param db
	 *            repository to register.
	 */
	public static void register(Repository db) {
		if (db.getDirectory() != null) {
			FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
			cache.registerRepository(key, db);
		}
	}

	/**
	 * Close and remove a repository from the cache.
	 * <p>
	 * Removes a repository from the cache, if it is still registered here, and
	 * close it.
	 *
	 * @param db
	 *            repository to unregister.
	 */
	public static void close(@NonNull Repository db) {
		if (db.getDirectory() != null) {
			FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
			cache.unregisterAndCloseRepository(key);
		}
	}

	/**
	 * Remove a repository from the cache.
	 * <p>
	 * Removes a repository from the cache, if it is still registered here. This
	 * method will not close the repository, only remove it from the cache. See
	 * {@link org.eclipse.jgit.lib.RepositoryCache#close(Repository)} to remove
	 * and close the repository.
	 *
	 * @param db
	 *            repository to unregister.
	 * @since 4.3
	 */
	public static void unregister(Repository db) {
		if (db.getDirectory() != null) {
			unregister(FileKey.exact(db.getDirectory(), db.getFS()));
		}
	}

	/**
	 * Remove a repository from the cache.
	 * <p>
	 * Removes a repository from the cache, if it is still registered here. This
	 * method will not close the repository, only remove it from the cache. See
	 * {@link org.eclipse.jgit.lib.RepositoryCache#close(Repository)} to remove
	 * and close the repository.
	 *
	 * @param location
	 *            location of the repository to remove.
	 * @since 4.1
	 */
	public static void unregister(Key location) {
		cache.unregisterRepository(location);
	}

	/**
	 * Get the locations of all repositories registered in the cache.
	 *
	 * @return the locations of all repositories registered in the cache.
	 * @since 4.1
	 */
	public static Collection<Key> getRegisteredKeys() {
		return cache.getKeys();
	}

	static boolean isCached(@NonNull Repository repo) {
		File gitDir = repo.getDirectory();
		if (gitDir == null) {
			return false;
		}
		FileKey key = new FileKey(gitDir, repo.getFS());
		return cache.cacheMap.get(key) == repo;
	}

	/**
	 * Unregister all repositories from the cache.
	 */
	public static void clear() {
		cache.clearAll();
	}

	static void clearExpired() {
		cache.clearAllExpired();
	}

	static void reconfigure(RepositoryCacheConfig repositoryCacheConfig) {
		cache.configureEviction(repositoryCacheConfig);
	}

	private final Map<Key, Repository> cacheMap;

	private final Lock[] openLocks;

	private ScheduledFuture<?> cleanupTask;

	private volatile long expireAfter;

	private final Object schedulerLock = new Lock();

	private RepositoryCache() {
		cacheMap = new ConcurrentHashMap<>();
		openLocks = new Lock[4];
		for (int i = 0; i < openLocks.length; i++) {
			openLocks[i] = new Lock();
		}
		configureEviction(new RepositoryCacheConfig());
	}

	private void configureEviction(
			RepositoryCacheConfig repositoryCacheConfig) {
		expireAfter = repositoryCacheConfig.getExpireAfter();
		ScheduledThreadPoolExecutor scheduler = WorkQueue.getExecutor();
		synchronized (schedulerLock) {
			if (cleanupTask != null) {
				cleanupTask.cancel(false);
			}
			long delay = repositoryCacheConfig.getCleanupDelay();
			if (delay == RepositoryCacheConfig.NO_CLEANUP) {
				return;
			}
			cleanupTask = scheduler.scheduleWithFixedDelay(() -> {
				try {
					cache.clearAllExpired();
				} catch (Throwable e) {
					LOG.error(e.getMessage(), e);
				}
			}, delay, delay, TimeUnit.MILLISECONDS);
		}
	}

	private Repository openRepository(final Key location,
			final boolean mustExist) throws IOException {
		Repository db = cacheMap.get(location);
		if (db == null) {
			synchronized (lockFor(location)) {
				db = cacheMap.get(location);
				if (db == null) {
					db = location.open(mustExist);
					cacheMap.put(location, db);
				} else {
					db.incrementOpen();
				}
			}
		} else {
			db.incrementOpen();
		}
		return db;
	}

	private void registerRepository(Key location, Repository db) {
		try (Repository oldDb = cacheMap.put(location, db)) {
			// oldDb is auto-closed
		}
	}

	private Repository unregisterRepository(Key location) {
		return cacheMap.remove(location);
	}

	private boolean isExpired(Repository db) {
		return db != null && db.useCnt.get() <= 0
			&& (System.currentTimeMillis() - db.closedAt.get() > expireAfter);
	}

	private void unregisterAndCloseRepository(Key location) {
		synchronized (lockFor(location)) {
			Repository oldDb = unregisterRepository(location);
			if (oldDb != null) {
				oldDb.doClose();
			}
		}
	}

	private Collection<Key> getKeys() {
		return new ArrayList<>(cacheMap.keySet());
	}

	private void clearAllExpired() {
		for (Repository db : cacheMap.values()) {
			if (isExpired(db)) {
				RepositoryCache.close(db);
			}
		}
	}

	private void clearAll() {
		for (Key k : cacheMap.keySet()) {
			unregisterAndCloseRepository(k);
		}
	}

	private Lock lockFor(Key location) {
		return openLocks[(location.hashCode() >>> 1) % openLocks.length];
	}

	private static class Lock {
		// Used only for its monitor.
	}

	/**
	 * Abstract hash key for {@link RepositoryCache} entries.
	 * <p>
	 * A Key instance should be lightweight, and implement hashCode() and
	 * equals() such that two Key instances are equal if they represent the same
	 * Repository location.
	 */
	public static interface Key {
		/**
		 * Called by {@link RepositoryCache#open(Key)} if it doesn't exist yet.
		 * <p>
		 * If a repository does not exist yet in the cache, the cache will call
		 * this method to acquire a handle to it.
		 *
		 * @param mustExist
		 *            true if the repository must exist in order to be opened;
		 *            false if a new non-existent repository is permitted to be
		 *            created (the caller is responsible for calling create).
		 * @return the new repository instance.
		 * @throws IOException
		 *             the repository could not be read (likely its core.version
		 *             property is not supported).
		 * @throws RepositoryNotFoundException
		 *             There is no repository at the given location, only thrown
		 *             if {@code mustExist} is true.
		 */
		Repository open(boolean mustExist) throws IOException,
				RepositoryNotFoundException;
	}

	/** Location of a Repository, using the standard java.io.File API. */
	public static class FileKey implements Key {
		/**
		 * Obtain a pointer to an exact location on disk.
		 * <p>
		 * No guessing is performed, the given location is exactly the GIT_DIR
		 * directory of the repository.
		 *
		 * @param directory
		 *            location where the repository database is.
		 * @param fs
		 *            the file system abstraction which will be necessary to
		 *            perform certain file system operations.
		 * @return a key for the given directory.
		 * @see #lenient(File, FS)
		 */
		public static FileKey exact(File directory, FS fs) {
			return new FileKey(directory, fs);
		}

		/**
		 * Obtain a pointer to a location on disk.
		 * <p>
		 * The method performs some basic guessing to locate the repository.
		 * Searched paths are:
		 * <ol>
		 * <li>{@code directory} // assume exact match</li>
		 * <li>{@code directory} + "/.git" // assume working directory</li>
		 * <li>{@code directory} + ".git" // assume bare</li>
		 * </ol>
		 *
		 * @param directory
		 *            location where the repository database might be.
		 * @param fs
		 *            the file system abstraction which will be necessary to
		 *            perform certain file system operations.
		 * @return a key for the given directory.
		 * @see #exact(File, FS)
		 */
		public static FileKey lenient(File directory, FS fs) {
			final File gitdir = resolve(directory, fs);
			return new FileKey(gitdir != null ? gitdir : directory, fs);
		}

		private final File path;
		private final FS fs;

		/**
		 * Create a pointer to a location on disk.
		 *
		 * @param directory
		 *            exact location of the repository.
		 * @param fs
		 *            the file system abstraction which will be necessary to
		 *            perform certain file system operations.
		 */
		protected FileKey(File directory, FS fs) {
			path = canonical(directory);
			this.fs = fs;
		}

		private static File canonical(File path) {
			try {
				return path.getCanonicalFile();
			} catch (IOException e) {
				return path.getAbsoluteFile();
			}
		}

		/**
		 * Get directory containing the repository database
		 *
		 * @return directory containing the repository database.
		 */
		public final File getFile() {
			return path;
		}

		@Override
		public Repository open(boolean mustExist) throws IOException {
			if (mustExist && !isGitRepository(path, fs))
				throw new RepositoryNotFoundException(path);
			return new FileRepository(path);
		}

		@Override
		public int hashCode() {
			return path.hashCode();
		}

		@Override
		public boolean equals(Object o) {
			return o instanceof FileKey && path.equals(((FileKey) o).path);
		}

		@Override
		public String toString() {
			return path.toString();
		}

		/**
		 * Guess if a directory contains a Git repository.
		 * <p>
		 * This method guesses by looking for the existence of some key files
		 * and directories.
		 *
		 * @param dir
		 *            the location of the directory to examine.
		 * @param fs
		 *            the file system abstraction which will be necessary to
		 *            perform certain file system operations.
		 * @return true if the directory "looks like" a Git repository; false if
		 *         it doesn't look enough like a Git directory to really be a
		 *         Git directory.
		 */
		public static boolean isGitRepository(File dir, FS fs) {
			return fs.resolve(dir, Constants.OBJECTS).exists()
					&& fs.resolve(dir, "refs").exists() //$NON-NLS-1$
					&& (fs.resolve(dir, Constants.REFTABLE).exists()
							|| isValidHead(new File(dir, Constants.HEAD)));
		}

		private static boolean isValidHead(File head) {
			final String ref = readFirstLine(head);
			return ref != null
					&& (ref.startsWith("ref: refs/") || ObjectId.isId(ref)); //$NON-NLS-1$
		}

		private static String readFirstLine(File head) {
			try {
				final byte[] buf = IO.readFully(head, 4096);
				int n = buf.length;
				if (n == 0)
					return null;
				if (buf[n - 1] == '\n')
					n--;
				return RawParseUtils.decode(buf, 0, n);
			} catch (IOException e) {
				return null;
			}
		}

		/**
		 * Guess the proper path for a Git repository.
		 * <p>
		 * The method performs some basic guessing to locate the repository.
		 * Searched paths are:
		 * <ol>
		 * <li>{@code directory} // assume exact match</li>
		 * <li>{@code directory} + "/.git" // assume working directory</li>
		 * <li>{@code directory} + ".git" // assume bare</li>
		 * </ol>
		 *
		 * @param directory
		 *            location to guess from. Several permutations are tried.
		 * @param fs
		 *            the file system abstraction which will be necessary to
		 *            perform certain file system operations.
		 * @return the actual directory location if a better match is found;
		 *         null if there is no suitable match.
		 */
		public static File resolve(File directory, FS fs) {
			if (isGitRepository(directory, fs))
				return directory;
			if (isGitRepository(new File(directory, Constants.DOT_GIT), fs))
				return new File(directory, Constants.DOT_GIT);

			final String name = directory.getName();
			final File parent = directory.getParentFile();
			if (isGitRepository(new File(parent, name + Constants.DOT_GIT_EXT), fs))
				return new File(parent, name + Constants.DOT_GIT_EXT);
			return null;
		}
	}
}
