Browse Source

Merge branch 'stable-4.11' into stable-5.0

* stable-4.11:
  Fix GC run in foreground to not use executor

Change-Id: I9bb1506805a2d5e79a420a1152bc45321c081229
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-5.0
Matthias Sohn 6 years ago
parent
commit
78d7d9916c
  1. 55
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
  2. 22
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java

55
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java

@ -77,15 +77,12 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CancelledException; import org.eclipse.jgit.errors.CancelledException;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
@ -248,8 +245,11 @@ public class GC {
*/ */
// TODO(ms): in 5.0 change signature and return Future<Collection<PackFile>> // TODO(ms): in 5.0 change signature and return Future<Collection<PackFile>>
public Collection<PackFile> gc() throws IOException, ParseException { public Collection<PackFile> gc() throws IOException, ParseException {
final GcLog gcLog = background ? new GcLog(repo) : null; if (!background) {
if (gcLog != null && !gcLog.lock(background)) { return doGc();
}
final GcLog gcLog = new GcLog(repo);
if (!gcLog.lock()) {
// there is already a background gc running // there is already a background gc running
return Collections.emptyList(); return Collections.emptyList();
} }
@ -257,48 +257,31 @@ public class GC {
Callable<Collection<PackFile>> gcTask = () -> { Callable<Collection<PackFile>> gcTask = () -> {
try { try {
Collection<PackFile> newPacks = doGc(); Collection<PackFile> newPacks = doGc();
if (automatic && tooManyLooseObjects() && gcLog != null) { if (automatic && tooManyLooseObjects()) {
String message = JGitText.get().gcTooManyUnpruned; String message = JGitText.get().gcTooManyUnpruned;
gcLog.write(message); gcLog.write(message);
gcLog.commit(); gcLog.commit();
} }
return newPacks; return newPacks;
} catch (IOException | ParseException e) { } catch (IOException | ParseException e) {
if (background) { try {
if (gcLog == null) { gcLog.write(e.getMessage());
// Lacking a log, there's no way to report this. StringWriter sw = new StringWriter();
return Collections.emptyList(); e.printStackTrace(new PrintWriter(sw));
} gcLog.write(sw.toString());
try { gcLog.commit();
gcLog.write(e.getMessage()); } catch (IOException e2) {
StringWriter sw = new StringWriter(); e2.addSuppressed(e);
e.printStackTrace(new PrintWriter(sw)); LOG.error(e2.getMessage(), e2);
gcLog.write(sw.toString());
gcLog.commit();
} catch (IOException e2) {
e2.addSuppressed(e);
LOG.error(e2.getMessage(), e2);
}
} else {
throw new JGitInternalException(e.getMessage(), e);
} }
} finally { } finally {
if (gcLog != null) { gcLog.unlock();
gcLog.unlock();
}
} }
return Collections.emptyList(); return Collections.emptyList();
}; };
Future<Collection<PackFile>> result = executor().submit(gcTask); // TODO(ms): in 5.0 change signature and return the Future
if (background) { executor().submit(gcTask);
// TODO(ms): in 5.0 change signature and return the Future return Collections.emptyList();
return Collections.emptyList();
}
try {
return result.get();
} catch (InterruptedException | ExecutionException e) {
throw new IOException(e);
}
} }
private ExecutorService executor() { private ExecutorService executor() {

22
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GcLog.java

@ -45,18 +45,15 @@ package org.eclipse.jgit.internal.storage.file;
import static org.eclipse.jgit.lib.Constants.CHARSET; import static org.eclipse.jgit.lib.Constants.CHARSET;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.attribute.FileTime; import java.nio.file.attribute.FileTime;
import java.text.MessageFormat;
import java.text.ParseException; import java.text.ParseException;
import java.time.Instant; import java.time.Instant;
import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.GitDateParser; import org.eclipse.jgit.util.GitDateParser;
@ -104,22 +101,11 @@ class GcLog {
return gcLogExpire; return gcLogExpire;
} }
private boolean autoGcBlockedByOldLockFile(boolean background) { private boolean autoGcBlockedByOldLockFile() {
try { try {
FileTime lastModified = Files.getLastModifiedTime(FileUtils.toPath(logFile)); FileTime lastModified = Files.getLastModifiedTime(FileUtils.toPath(logFile));
if (lastModified.toInstant().compareTo(getLogExpiry()) > 0) { if (lastModified.toInstant().compareTo(getLogExpiry()) > 0) {
// There is an existing log file, which is too recent to ignore // There is an existing log file, which is too recent to ignore
if (!background) {
try (BufferedReader reader = Files
.newBufferedReader(FileUtils.toPath(logFile))) {
char[] buf = new char[1000];
int len = reader.read(buf, 0, 1000);
String oldError = new String(buf, 0, len);
throw new JGitInternalException(MessageFormat.format(
JGitText.get().gcLogExists, oldError, logFile));
}
}
return true; return true;
} }
} catch (NoSuchFileException e) { } catch (NoSuchFileException e) {
@ -133,11 +119,9 @@ class GcLog {
/** /**
* Lock the GC log file for updates * Lock the GC log file for updates
* *
* @param background
* If true, and if gc.log already exists, unlock and return false
* @return {@code true} if we hold the lock * @return {@code true} if we hold the lock
*/ */
boolean lock(boolean background) { boolean lock() {
try { try {
if (!lock.lock()) { if (!lock.lock()) {
return false; return false;
@ -145,7 +129,7 @@ class GcLog {
} catch (IOException e) { } catch (IOException e) {
throw new JGitInternalException(e.getMessage(), e); throw new JGitInternalException(e.getMessage(), e);
} }
if (autoGcBlockedByOldLockFile(background)) { if (autoGcBlockedByOldLockFile()) {
lock.unlock(); lock.unlock();
return false; return false;
} }

Loading…
Cancel
Save