Browse Source

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 <spearce@spearce.org>
stable-0.12
Shawn O. Pearce 14 years ago committed by Chris Aniszczyk
parent
commit
c261b28f67
  1. 4
      org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/RefDirectoryTest.java
  2. 14
      org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileSnapshot.java
  3. 20
      org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LockFile.java
  4. 35
      org.eclipse.jgit/src/org/eclipse/jgit/storage/file/RefDirectory.java

4
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 { private void writePackedRefs(String content) throws IOException {
File pr = new File(diskRepo.getDirectory(), "packed-refs"); File pr = new File(diskRepo.getDirectory(), "packed-refs");
write(pr, content); write(pr, content);
final long now = System.currentTimeMillis();
final int oneHourAgo = 3600 * 1000;
pr.setLastModified(now - oneHourAgo);
} }
private void deleteLooseRef(String name) { private void deleteLooseRef(String name) {

14
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); public static final FileSnapshot DIRTY = new FileSnapshot(-1, -1);
/**
* A FileSnapshot that is clean if the file does not exist.
* <p>
* 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. * Record a snapshot for a specific file path.
* <p> * <p>

20
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. * Wait until the lock file information differs from the old file.
* <p> * <p>
* This method tests both the length and the last modification date. If both * This method tests the last modification date. If both are the same, this
* are the same, this method sleeps until it can force the new lock file's * method sleeps until it can force the new lock file's modification date to
* modification date to be later than the target file. * be later than the target file.
* *
* @throws InterruptedException * @throws InterruptedException
* the thread was interrupted before the last modified date of * the thread was interrupted before the last modified date of
@ -378,14 +378,12 @@ public class LockFile {
* the target file. * the target file.
*/ */
public void waitForStatChange() throws InterruptedException { public void waitForStatChange() throws InterruptedException {
if (ref.length() == lck.length()) { FileSnapshot o = FileSnapshot.save(ref);
long otime = ref.lastModified(); FileSnapshot n = FileSnapshot.save(lck);
long ntime = lck.lastModified(); while (o.equals(n)) {
while (otime == ntime) { Thread.sleep(25 /* milliseconds */);
Thread.sleep(25 /* milliseconds */); lck.setLastModified(System.currentTimeMillis());
lck.setLastModified(System.currentTimeMillis()); n = FileSnapshot.save(lck);
ntime = lck.lastModified();
}
} }
} }

35
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( throw new IOException(MessageFormat.format(
JGitText.get().cannotLockFile, packedRefsFile)); JGitText.get().cannotLockFile, packedRefsFile));
try { try {
PackedRefList cur = readPackedRefs(0, 0); PackedRefList cur = readPackedRefs();
int idx = cur.find(name); int idx = cur.find(name);
if (0 <= idx) if (0 <= idx)
commitPackedRefs(lck, cur.remove(idx), packed); commitPackedRefs(lck, cur.remove(idx), packed);
@ -690,21 +690,19 @@ public class RefDirectory extends RefDatabase {
} }
private PackedRefList getPackedRefs() throws IOException { private PackedRefList getPackedRefs() throws IOException {
long size = packedRefsFile.length();
long mtime = size != 0 ? packedRefsFile.lastModified() : 0;
final PackedRefList curList = packedRefs.get(); final PackedRefList curList = packedRefs.get();
if (size == curList.lastSize && mtime == curList.lastModified) if (!curList.snapshot.isModified(packedRefsFile))
return curList; return curList;
final PackedRefList newList = readPackedRefs(size, mtime); final PackedRefList newList = readPackedRefs();
if (packedRefs.compareAndSet(curList, newList)) if (packedRefs.compareAndSet(curList, newList))
modCnt.incrementAndGet(); modCnt.incrementAndGet();
return newList; return newList;
} }
private PackedRefList readPackedRefs(long size, long mtime) private PackedRefList readPackedRefs()
throws IOException { throws IOException {
final FileSnapshot snapshot = FileSnapshot.save(packedRefsFile);
final BufferedReader br; final BufferedReader br;
try { try {
br = new BufferedReader(new InputStreamReader(new FileInputStream( br = new BufferedReader(new InputStreamReader(new FileInputStream(
@ -714,7 +712,7 @@ public class RefDirectory extends RefDatabase {
return PackedRefList.NO_PACKED_REFS; return PackedRefList.NO_PACKED_REFS;
} }
try { try {
return new PackedRefList(parsePackedRefs(br), size, mtime); return new PackedRefList(parsePackedRefs(br), snapshot);
} finally { } finally {
br.close(); br.close();
} }
@ -780,7 +778,7 @@ public class RefDirectory extends RefDatabase {
protected void writeFile(String name, byte[] content) protected void writeFile(String name, byte[] content)
throws IOException { throws IOException {
lck.setFSync(true); lck.setFSync(true);
lck.setNeedStatInformation(true); lck.setNeedSnapshot(true);
try { try {
lck.write(content); lck.write(content);
} catch (IOException ioe) { } catch (IOException ioe) {
@ -795,8 +793,8 @@ public class RefDirectory extends RefDatabase {
if (!lck.commit()) if (!lck.commit())
throw new ObjectWritingException(MessageFormat.format(JGitText.get().unableToWrite, name)); throw new ObjectWritingException(MessageFormat.format(JGitText.get().unableToWrite, name));
packedRefs.compareAndSet(oldPackedList, new PackedRefList(refs, packedRefs.compareAndSet(oldPackedList, new PackedRefList(
content.length, lck.getCommitLastModified())); refs, lck.getCommitSnapshot()));
} }
}.writePackedRefs(); }.writePackedRefs();
} }
@ -968,19 +966,14 @@ public class RefDirectory extends RefDatabase {
} }
private static class PackedRefList extends RefList<Ref> { private static class PackedRefList extends RefList<Ref> {
static final PackedRefList NO_PACKED_REFS = new PackedRefList(RefList static final PackedRefList NO_PACKED_REFS = new PackedRefList(
.emptyList(), 0, 0); RefList.emptyList(), FileSnapshot.MISSING_FILE);
/** Last length of the packed-refs file when we read it. */
final long lastSize;
/** Last modified time of the packed-refs file when we read it. */ final FileSnapshot snapshot;
final long lastModified;
PackedRefList(RefList<Ref> src, long size, long mtime) { PackedRefList(RefList<Ref> src, FileSnapshot s) {
super(src); super(src);
lastSize = size; snapshot = s;
lastModified = mtime;
} }
} }

Loading…
Cancel
Save