From c261b28f677fdc755b86d16abebd2c30093514b4 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 13 Dec 2010 13:41:19 -0800 Subject: [PATCH] RefDirectory: Use FileSnapshot for packed-refs Instead of tracking the length and modification time by hand, rely on FileSnapshot to tell RefDirectory when the $GIT_DIR/packed-refs file has been changed or should be re-read from disk. Change-Id: I067d268dfdca1d39c72dfa536b34e6a239117cc3 Signed-off-by: Shawn O. Pearce --- .../jgit/storage/file/RefDirectoryTest.java | 4 +++ .../jgit/storage/file/FileSnapshot.java | 14 ++++++++ .../eclipse/jgit/storage/file/LockFile.java | 20 +++++------ .../jgit/storage/file/RefDirectory.java | 35 ++++++++----------- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java index 2a1302232..a61580dd1 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java @@ -1055,6 +1055,10 @@ public class RefDirectoryTest extends LocalDiskRepositoryTestCase { private void writePackedRefs(String content) throws IOException { File pr = new File(diskRepo.getDirectory(), "packed-refs"); write(pr, content); + + final long now = System.currentTimeMillis(); + final int oneHourAgo = 3600 * 1000; + pr.setLastModified(now - oneHourAgo); } private void deleteLooseRef(String name) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileSnapshot.java index 0e5b3c00b..bbec80c86 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileSnapshot.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileSnapshot.java @@ -71,6 +71,20 @@ public class FileSnapshot { */ public static final FileSnapshot DIRTY = new FileSnapshot(-1, -1); + /** + * A FileSnapshot that is clean if the file does not exist. + *

+ * This instance is useful if the application wants to consider a missing + * file to be clean. {@link #isModified(File)} will return false if the file + * path does not exist. + */ + public static final FileSnapshot MISSING_FILE = new FileSnapshot(0, 0) { + @Override + public boolean isModified(File path) { + return path.exists(); + } + }; + /** * Record a snapshot for a specific file path. *

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java index 9e637ab4f..6acd7132a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java @@ -368,9 +368,9 @@ public class LockFile { /** * Wait until the lock file information differs from the old file. *

- * This method tests both the length and the last modification date. If both - * are the same, this method sleeps until it can force the new lock file's - * modification date to be later than the target file. + * This method tests the last modification date. If both are the same, this + * method sleeps until it can force the new lock file's modification date to + * be later than the target file. * * @throws InterruptedException * the thread was interrupted before the last modified date of @@ -378,14 +378,12 @@ public class LockFile { * the target file. */ public void waitForStatChange() throws InterruptedException { - if (ref.length() == lck.length()) { - long otime = ref.lastModified(); - long ntime = lck.lastModified(); - while (otime == ntime) { - Thread.sleep(25 /* milliseconds */); - lck.setLastModified(System.currentTimeMillis()); - ntime = lck.lastModified(); - } + FileSnapshot o = FileSnapshot.save(ref); + FileSnapshot n = FileSnapshot.save(lck); + while (o.equals(n)) { + Thread.sleep(25 /* milliseconds */); + lck.setLastModified(System.currentTimeMillis()); + n = FileSnapshot.save(lck); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java index c3402df67..8ac08efb8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java @@ -548,7 +548,7 @@ public class RefDirectory extends RefDatabase { throw new IOException(MessageFormat.format( JGitText.get().cannotLockFile, packedRefsFile)); try { - PackedRefList cur = readPackedRefs(0, 0); + PackedRefList cur = readPackedRefs(); int idx = cur.find(name); if (0 <= idx) commitPackedRefs(lck, cur.remove(idx), packed); @@ -690,21 +690,19 @@ public class RefDirectory extends RefDatabase { } private PackedRefList getPackedRefs() throws IOException { - long size = packedRefsFile.length(); - long mtime = size != 0 ? packedRefsFile.lastModified() : 0; - final PackedRefList curList = packedRefs.get(); - if (size == curList.lastSize && mtime == curList.lastModified) + if (!curList.snapshot.isModified(packedRefsFile)) return curList; - final PackedRefList newList = readPackedRefs(size, mtime); + final PackedRefList newList = readPackedRefs(); if (packedRefs.compareAndSet(curList, newList)) modCnt.incrementAndGet(); return newList; } - private PackedRefList readPackedRefs(long size, long mtime) + private PackedRefList readPackedRefs() throws IOException { + final FileSnapshot snapshot = FileSnapshot.save(packedRefsFile); final BufferedReader br; try { br = new BufferedReader(new InputStreamReader(new FileInputStream( @@ -714,7 +712,7 @@ public class RefDirectory extends RefDatabase { return PackedRefList.NO_PACKED_REFS; } try { - return new PackedRefList(parsePackedRefs(br), size, mtime); + return new PackedRefList(parsePackedRefs(br), snapshot); } finally { br.close(); } @@ -780,7 +778,7 @@ public class RefDirectory extends RefDatabase { protected void writeFile(String name, byte[] content) throws IOException { lck.setFSync(true); - lck.setNeedStatInformation(true); + lck.setNeedSnapshot(true); try { lck.write(content); } catch (IOException ioe) { @@ -795,8 +793,8 @@ public class RefDirectory extends RefDatabase { if (!lck.commit()) throw new ObjectWritingException(MessageFormat.format(JGitText.get().unableToWrite, name)); - packedRefs.compareAndSet(oldPackedList, new PackedRefList(refs, - content.length, lck.getCommitLastModified())); + packedRefs.compareAndSet(oldPackedList, new PackedRefList( + refs, lck.getCommitSnapshot())); } }.writePackedRefs(); } @@ -968,19 +966,14 @@ public class RefDirectory extends RefDatabase { } private static class PackedRefList extends RefList { - static final PackedRefList NO_PACKED_REFS = new PackedRefList(RefList - .emptyList(), 0, 0); - - /** Last length of the packed-refs file when we read it. */ - final long lastSize; + static final PackedRefList NO_PACKED_REFS = new PackedRefList( + RefList.emptyList(), FileSnapshot.MISSING_FILE); - /** Last modified time of the packed-refs file when we read it. */ - final long lastModified; + final FileSnapshot snapshot; - PackedRefList(RefList src, long size, long mtime) { + PackedRefList(RefList src, FileSnapshot s) { super(src); - lastSize = size; - lastModified = mtime; + snapshot = s; } }