Mercurial > hg > mercurial
view mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManager.java @ 279:01a64fe3b896 Eluru-6.5.x
Remove private data from the logs
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Thu, 11 Aug 2011 09:33:20 +0400 |
parents | 928d3da0fe8b |
children | e0464f11206c |
line wrap: on
line source
package jetbrains.buildServer.buildTriggers.vcs.mercurial; import com.intellij.openapi.diagnostic.Logger; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.Hash; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Manages local mirrors of remote repositories. * Each unique url get unique local mirror. Each mirror is used for one url only. * @author dmitry.neverov */ public final class MirrorManager { private static Logger LOG = Logger.getInstance(MirrorManager.class.getName()); private static final String MIRROR_DIR_PREFIX = "hg_"; private static final String MAPPING_FILE_NAME = "map"; private final ReadWriteLock myLock = new ReentrantReadWriteLock(); private final File myRootDir; /*Only one thread read or write to this file, it is protected by myLock.writeLock()*/ private final File myMappingFile; /*Protected by myLock*/ private final Map<String, File> myMirrors = new HashMap<String, File>(); private HashCalculator myHash = new StandartHash(); /** * @param rootDir root directory where all mirrors are stored */ public MirrorManager(File rootDir) { myRootDir = rootDir; myMappingFile = new File(myRootDir, MAPPING_FILE_NAME); readMappingFromFile(); } /** * Get directory of local mirror repository for specified url, if directory is not exists it is created * @param url url of interest * @return see above */ @NotNull public File getMirrorDir(@NotNull final String url) { File result = getMirrorDirWithLock(url); if (result == null) { result = createDirFor(url); } return result; } /** * Get all local mirror repository dirs * @return see above */ @NotNull public List<File> getMirrors() { myLock.readLock().lock(); try { return new ArrayList<File>(myMirrors.values()); } finally { myLock.readLock().unlock(); } } //for tests only void setHashCalculator(HashCalculator hash) { myHash = hash; } private File createDirFor(String url) { File result; myLock.writeLock().lock(); try { File mirrorDir = getUniqueDir(url); result = saveMappingIfAbsent(url, mirrorDir); } finally { myLock.writeLock().unlock(); } if (!result.exists()) { result.mkdirs(); } return result; } private File getMirrorDirWithLock(String url) { myLock.readLock().lock(); try { return myMirrors.get(url); } finally { myLock.readLock().unlock(); } } //should be called with myLock.writeLock() held private File saveMappingIfAbsent(String url, File mirrorDir) { File existing = myMirrors.get(url); if (existing != null) { return existing; } else { myMirrors.put(url, mirrorDir); saveMappingToFile(); return mirrorDir; } } private File getUniqueDir(String url) { myLock.readLock().lock(); try { String dirName = MIRROR_DIR_PREFIX + hash(normalize(url)); File result = PathUtil.getCanonicalFile(new File(myRootDir, dirName)); while (isUsedForOtherUrl(result, url)) { dirName = MIRROR_DIR_PREFIX + hash(result.getName()); result = PathUtil.getCanonicalFile(new File(myRootDir, dirName)); } return result; } finally { myLock.readLock().unlock(); } } private boolean isUsedForOtherUrl(File repositoryDir, String url) { myLock.readLock().lock(); try { for (Map.Entry<String, File> mirror : myMirrors.entrySet()) { String mirrorUrl = mirror.getKey(); File mirrorDir = mirror.getValue(); if (mirrorDir.equals(repositoryDir) && !mirrorUrl.equals(url)) { return true; } } return false; } finally { myLock.readLock().unlock(); } } private String hash(String value) { return String.valueOf(myHash.calc(value)); } private static String normalize(final String path) { String normalized = PathUtil.normalizeSeparator(path); if (path.endsWith("/")) { return normalized.substring(0, normalized.length()-1); } return normalized; } private void readMappingFromFile() { myLock.writeLock().lock(); try { LOG.debug("Parse mapping file " + myMappingFile.getAbsolutePath()); for (String line : readLines()) { int separatorIndex = line.lastIndexOf(" = "); if (separatorIndex == -1) { if (!line.equals("")) LOG.warn("Cannot parse mapping '" + line + "', skip it."); } else { String url = line.substring(0, separatorIndex); String dirName = line.substring(separatorIndex + 3); File repositoryDir = PathUtil.getCanonicalFile(new File(myRootDir, dirName)); if (isUsedForOtherUrl(repositoryDir, url)) { LOG.error("Skip mapping " + line + ": " + dirName + " is used for url other than " + url); } else { myMirrors.put(url, PathUtil.getCanonicalFile(new File(myRootDir, dirName))); } } } } finally { myLock.writeLock().unlock(); } } /*Should be called with myLock.writeLock() held*/ private List<String> readLines() { if (myMappingFile.exists()) { try { return FileUtil.readFile(myMappingFile); } catch (IOException e) { LOG.error("Error while reading a mapping file at " + myMappingFile.getAbsolutePath() + " starting with empty mapping", e); return new ArrayList<String>(); } } else { LOG.debug("No mapping file found at " + myMappingFile.getAbsolutePath() + " starting with empty mapping"); File parentDir = myMappingFile.getParentFile(); if (!parentDir.exists() && !parentDir.mkdirs()) { LOG.error("Cannot create local mirrors dir at " + parentDir.getAbsolutePath()); } else { try { if (!myMappingFile.createNewFile()) LOG.warn("Someone else creates a mapping file " + myMappingFile.getAbsolutePath() + ", will use it"); } catch (IOException e) { LOG.error("Cannot create a mapping file at " + myMappingFile.getAbsolutePath(), e); } } return new ArrayList<String>(); } } private void saveMappingToFile() { myLock.writeLock().lock(); try { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, File> mirror : myMirrors.entrySet()) { String url = mirror.getKey(); String dir = mirror.getValue().getName(); sb.append(url).append(" = ").append(dir).append("\n"); } FileUtil.writeFile(myMappingFile, sb.toString()); } finally { myLock.writeLock().unlock(); } } final static class StandartHash implements HashCalculator { public long calc(String value) { return Hash.calc(value); } } public static interface HashCalculator { long calc(String value); } }