avoid calling expensive getCanonical when we create locks for repository directories...
authorpavel.sher <pavel.sher@jetbrains.com>
Thu, 12 Jul 2018 18:08:11 +0000 (20:08 +0200)
committerpavel.sher <pavel.sher@jetbrains.com>
Thu, 12 Jul 2018 18:08:11 +0000 (20:08 +0200)
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/RepositoryManager.java
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/RepositoryManagerImpl.java

index 18cc621681ef4d7f56160de4e981bf33cd92348b..7c7576b1a46e35d90b6d46ed90c356ea36d2d943 100644 (file)
@@ -42,10 +42,10 @@ public interface RepositoryManager extends MirrorManager {
   void closeRepository(@NotNull Repository repository);
 
   @NotNull
-  public Object getWriteLock(@NotNull File dir);
+  Object getWriteLock(@NotNull File dir);
 
   @NotNull
-  public ReadWriteLock getRmLock(@NotNull File dir);
+  ReadWriteLock getRmLock(@NotNull File dir);
 
   <T> T runWithDisabledRemove(@NotNull File dir, @NotNull VcsOperation<T> operation) throws VcsException;
 
index fa5ac51f31c33510d8ed0a72932db246363ce0a2..dac9175853fd149264da5c8a908284a3fb7ebd3e 100644 (file)
@@ -54,21 +54,21 @@ public final class RepositoryManagerImpl implements RepositoryManager {
    * try to create repository concurrently some of them could see it in inconsistent state. This map contains
    * locks for repository creation, so only one thread at a time will create repository at give dir.
    */
-  private final ConcurrentMap<File, Object> myCreateLocks = new ConcurrentHashMap<File, Object>();
+  private final ConcurrentMap<String, Object> myCreateLocks = new ConcurrentHashMap<>();
   /**
    * In the past jgit has some concurrency problems, in order to fix them we do only one fetch at a time.
    * Also several concurrent fetches in single repository does not make sense since only one of them succeed.
    * This map contains locks used for fetch and push operations.
    */
-  private final ConcurrentMap<File, Object> myWriteLocks = new ConcurrentHashMap<File, Object>();
+  private final ConcurrentMap<String, Object> myWriteLocks = new ConcurrentHashMap<>();
   /**
    * During cleanup unused bare repositories are removed. This map contains rw locks for repository removal.
    * Fetch/push/create operations should be done with read lock hold, remove operation is done with write lock hold.
    * @see Cleanup
    */
-  private final ConcurrentMap<File, ReadWriteLock> myRmLocks = new ConcurrentHashMap<File, ReadWriteLock>();
+  private final ConcurrentMap<String, ReadWriteLock> myRmLocks = new ConcurrentHashMap<>();
 
-  private final ConcurrentMap<File, Object> myUpdateLastUsedTimeLocks = new ConcurrentHashMap<File, Object>();
+  private final ConcurrentMap<String, Object> myUpdateLastUsedTimeLocks = new ConcurrentHashMap<>();
 
   //repo dir -> last access time (nano seconds)
   private final ConcurrentMap<File, Long> myLastAccessTime = new ConcurrentHashMap<>();
@@ -215,34 +215,30 @@ public final class RepositoryManagerImpl implements RepositoryManager {
 
   @NotNull
   private Object getUpdateLastUsedTimeLock(@NotNull File dir) {
-    try {
-      File canonical = dir.getCanonicalFile();
-      return getOrCreate(myUpdateLastUsedTimeLocks, canonical, new Object());
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    return getOrCreate(myUpdateLastUsedTimeLocks, getCanonicalName(dir), new Object());
   }
 
 
   @NotNull
   public Object getWriteLock(@NotNull final File dir) {
-    try {
-      File canonical = dir.getCanonicalFile();
-      return getOrCreate(myWriteLocks, canonical, new Object());
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    return getOrCreate(myWriteLocks, getCanonicalName(dir), new Object());
   }
 
 
   @NotNull
   public ReadWriteLock getRmLock(@NotNull final File dir) {
-    try {
-      File canonical = dir.getCanonicalFile();
-      return getOrCreate(myRmLocks, canonical, new ReentrantReadWriteLock());
-    } catch (IOException e) {
-      throw new RuntimeException(e);
+    return getOrCreate(myRmLocks, getCanonicalName(dir), new ReentrantReadWriteLock());
+  }
+
+  @NotNull
+  private String getCanonicalName(final @NotNull File dir) {
+    String name = dir.getName();
+    if (".".equals(name) || "..".equals(name)) {
+      // call getCanonical in special cases only
+      return FileUtil.getCanonicalFile(dir).getName();
     }
+
+    return name;
   }
 
 
@@ -271,24 +267,15 @@ public final class RepositoryManagerImpl implements RepositoryManager {
 
   @NotNull
   public Object getCreateLock(File dir) {
-    try {
-      File canonical = dir.getCanonicalFile();
-      return getOrCreate(myCreateLocks, canonical, new Object());
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    return getOrCreate(myCreateLocks, getCanonicalName(dir), new Object());
   }
 
 
   public void cleanLocksFor(@NotNull final File dir) {
-    try {
-      File canonical = dir.getCanonicalFile();
-      myWriteLocks.remove(canonical);
-      myCreateLocks.remove(canonical);
-      myRmLocks.remove(canonical);
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
+    final String canonicalName = getCanonicalName(dir);
+    myWriteLocks.remove(canonicalName);
+    myCreateLocks.remove(canonicalName);
+    myRmLocks.remove(canonicalName);
   }
 
   private <K, V> V getOrCreate(ConcurrentMap<K, V> map, K key, V value) {