Browse Source

Fix pack files scan when filesnapshot isn't modified

Do not reload packfiles when their associated filesnapshot is not
modified on disk compared to the one currently stored in memory.

Fix the regression introduced by fef78212 which, in conjunction with
core.trustfolderstats = false, caused any lookup of objects inside
the packlist to loop forever when the object was not found in the pack
list.

Bug: 546190
Change-Id: I38d752ebe47cefc3299740aeba319a2641f19391
Signed-off-by: Luca Milanesio <luca.milanesio@gmail.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v4.5.7.201904151645-r
Luca Milanesio 5 years ago
parent
commit
82b1af31e2

+ 48
- 1
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/ObjectDirectoryTest.java View File



package org.eclipse.jgit.internal.storage.file; package org.eclipse.jgit.internal.storage.file;


import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;


import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;


@RunWith(Parameterized.class)
public class ObjectDirectoryTest extends RepositoryTestCase { public class ObjectDirectoryTest extends RepositoryTestCase {


@Parameter
public Boolean trustFolderStats;

@Parameters(name= "core.trustfolderstat={0}")
public static Iterable<? extends Object> data() {
return Arrays.asList(Boolean.TRUE, Boolean.FALSE);
}

@Test @Test
public void testConcurrentInsertionOfBlobsToTheSameNewFanOutDirectory() public void testConcurrentInsertionOfBlobsToTheSameNewFanOutDirectory()
throws Exception { throws Exception {
} }
} }


@Test
public void testShouldNotSearchPacksAgainTheSecondTime() throws Exception {
FileRepository bareRepository = newTestRepositoryWithOnePackfile();
ObjectDirectory dir = bareRepository.getObjectDatabase();

// Make sure that timestamps are modified and read so that a full
// file snapshot check is performed
Thread.sleep(3000L);

assertTrue(dir.searchPacksAgain(dir.packList.get()));
assertFalse(dir.searchPacksAgain(dir.packList.get()));
}

private FileRepository newTestRepositoryWithOnePackfile() throws Exception {
FileRepository repository = createBareRepository();
TestRepository<FileRepository> testRepository = new TestRepository<FileRepository>(repository);
testRepository.commit();
testRepository.packAndPrune();

FileBasedConfig repoConfig = repository.getConfig();
repoConfig.setBoolean(ConfigConstants.CONFIG_CORE_SECTION,null,
ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT,
trustFolderStats.booleanValue());
repoConfig.save();

return repository;
}

private Collection<Callable<ObjectId>> blobInsertersForTheSameFanOutDir( private Collection<Callable<ObjectId>> blobInsertersForTheSameFanOutDir(
final ObjectDirectory dir) { final ObjectDirectory dir) {
Callable<ObjectId> callable = new Callable<ObjectId>() { Callable<ObjectId> callable = new Callable<ObjectId>() {

+ 6
- 5
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java View File



private final File alternatesFile; private final File alternatesFile;


private final AtomicReference<PackList> packList;

private final FS fs; private final FS fs;


private final AtomicReference<AlternateHandle[]> alternates; private final AtomicReference<AlternateHandle[]> alternates;


private Set<ObjectId> shallowCommitsIds; private Set<ObjectId> shallowCommitsIds;


final AtomicReference<PackList> packList;

/** /**
* Initialize a reference to an on-disk object directory. * Initialize a reference to an on-disk object directory.
* *
return InsertLooseObjectResult.FAILURE; return InsertLooseObjectResult.FAILURE;
} }


private boolean searchPacksAgain(PackList old) {
boolean searchPacksAgain(PackList old) {
// Whether to trust the pack folder's modification time. If set // Whether to trust the pack folder's modification time. If set
// to false we will always scan the .git/objects/pack folder to // to false we will always scan the .git/objects/pack folder to
// check for new pack files. If set to true (default) we use the // check for new pack files. If set to true (default) we use the
final String packName = base + PACK.getExtension(); final String packName = base + PACK.getExtension();
final File packFile = new File(packDirectory, packName); final File packFile = new File(packDirectory, packName);
final PackFile oldPack = forReuse.remove(packName); final PackFile oldPack = forReuse.remove(packName);
if (oldPack != null && oldPack.getFileSnapshot().isModified(packFile)) {
if (oldPack != null
&& !oldPack.getFileSnapshot().isModified(packFile)) {
list.add(oldPack); list.add(oldPack);
continue; continue;
} }
return new File(new File(getDirectory(), d), f); return new File(new File(getDirectory(), d), f);
} }


private static final class PackList {
static final class PackList {
/** State just before reading the pack directory. */ /** State just before reading the pack directory. */
final FileSnapshot snapshot; final FileSnapshot snapshot;



Loading…
Cancel
Save