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>
This commit is contained in:
parent
58ed0cb840
commit
c261b28f67
|
@ -1055,6 +1055,10 @@ private void writePackedRef(String name, AnyObjectId id) throws IOException {
|
|||
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) {
|
||||
|
|
|
@ -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.
|
||||
* <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.
|
||||
* <p>
|
||||
|
|
|
@ -368,9 +368,9 @@ public void setFSync(final boolean on) {
|
|||
/**
|
||||
* Wait until the lock file information differs from the old file.
|
||||
* <p>
|
||||
* 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 void setFSync(final boolean on) {
|
|||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ void delete(RefDirectoryUpdate update) throws IOException {
|
|||
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 @@ else if (0 <= (idx = packed.find(dst.getName())))
|
|||
}
|
||||
|
||||
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 @@ private PackedRefList readPackedRefs(long size, long mtime)
|
|||
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 @@ private void commitPackedRefs(final LockFile lck, final RefList<Ref> refs,
|
|||
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 @@ protected void writeFile(String name, byte[] content)
|
|||
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 @@ static void delete(final File file, final int depth) throws IOException {
|
|||
}
|
||||
|
||||
private static class PackedRefList extends RefList<Ref> {
|
||||
static final PackedRefList NO_PACKED_REFS = new PackedRefList(RefList
|
||||
.emptyList(), 0, 0);
|
||||
static final PackedRefList NO_PACKED_REFS = new PackedRefList(
|
||||
RefList.emptyList(), FileSnapshot.MISSING_FILE);
|
||||
|
||||
/** Last length of the packed-refs file when we read it. */
|
||||
final long lastSize;
|
||||
final FileSnapshot snapshot;
|
||||
|
||||
/** Last modified time of the packed-refs file when we read it. */
|
||||
final long lastModified;
|
||||
|
||||
PackedRefList(RefList<Ref> src, long size, long mtime) {
|
||||
PackedRefList(RefList<Ref> src, FileSnapshot s) {
|
||||
super(src);
|
||||
lastSize = size;
|
||||
lastModified = mtime;
|
||||
snapshot = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue