view mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialResetCacheHandler.java @ 1024:c0c4bf1db865

TW-66329 fix using archive command for creating full patch: previous implementation using clone produces very large overhead for big project repositories in case when settings are stored in the project repo since in case of freezing build settings, core system asks plugin to build full patch and cloning repos into temp dir even from local mirror can take tens of minutes
author Maxim Zaytsev <Maxim.Zaytsev@jetbrains.com>
date Mon, 15 Jun 2020 13:07:12 +0300
parents 7bf4d943d5bb
children
line wrap: on
line source
/*
 * Copyright 2000-2018 JetBrains s.r.o.
 *
 * 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 jetbrains.buildServer.buildTriggers.vcs.mercurial;

import com.intellij.openapi.diagnostic.Logger;
import jetbrains.buildServer.util.cache.ResetCacheHandler;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.intellij.openapi.util.io.FileUtil.delete;
import static java.util.Collections.singletonList;

/**
 * @author dmitry.neverov
 */
public class MercurialResetCacheHandler implements ResetCacheHandler {

  private static Logger LOG = Logger.getInstance(MercurialResetCacheHandler.class.getName());
  private static final String MERCURIAL_CACHE_NAME = "mercurial";

  private final MirrorManager myMirrorManager;
  private AtomicBoolean myResetRunning = new AtomicBoolean(false);

  public MercurialResetCacheHandler(@NotNull MirrorManager mirrorManager) {
    myMirrorManager = mirrorManager;
  }

  @NotNull
  public List<String> listCaches() {
    return singletonList(MERCURIAL_CACHE_NAME);
  }

  public boolean isEmpty(@NotNull final String cache) {
    return myMirrorManager.getMappings().isEmpty();
  }

  public void resetCache(@NotNull final String cache) {
    boolean started = startReset();
    if (!started) {
      LOG.info("Mercurial mirrors reset is already running");
      return;
    }
    resetAllMirrors();
    finishReset();
  }

  private boolean startReset() {
    return myResetRunning.compareAndSet(false, true);
  }

  private void finishReset() {
    myResetRunning.set(false);
  }

  private void resetAllMirrors() {
    LOG.info("Start reseting mercurial caches");
    for (Map.Entry<String, File> entry : myMirrorManager.getMappings().entrySet()) {
      String url = entry.getKey();
      File mirror = entry.getValue();
      try {
        lockMirror(url, mirror);
        resetMirror(mirror);
      } finally {
        unlockMirror(url, mirror);
      }
    }
    LOG.info("Mercurial caches reset");
  }

  private void lockMirror(@NotNull final String url, @NotNull final File mirror) {
    LOG.debug("Lock mirror of " + url);
    myMirrorManager.lockDir(mirror);
    LOG.debug("Mirror of " + url + " is locked");
  }

  private void resetMirror(@NotNull final File mirror) {
    LOG.debug("Reset mercurial mirror "  + mirror.getAbsolutePath());
    myMirrorManager.forgetDir(mirror);
    delete(mirror);
    LOG.debug("Mercurial mirror "  + mirror.getAbsolutePath() + " reset");
  }

  private void unlockMirror(@NotNull final String url, @NotNull final File mirror) {
    myMirrorManager.unlockDir(mirror);
    LOG.debug("Mirror of " + url + " is unlocked");
  }
}