/* * Copyright (C) 2017, Google Inc. and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * https://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.internal.storage.dfs; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.internal.storage.reftable.MergedReftable; import org.eclipse.jgit.internal.storage.reftable.ReftableConfig; import org.eclipse.jgit.internal.storage.reftable.ReftableDatabase; import org.eclipse.jgit.lib.BatchRefUpdate; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.util.RefList; import org.eclipse.jgit.util.RefMap; /** * A {@link org.eclipse.jgit.internal.storage.dfs.DfsRefDatabase} that uses * reftable for storage. *
* A {@code DfsRefDatabase} instance is thread-safe. *
* Implementors may wish to use
* {@link org.eclipse.jgit.internal.storage.dfs.DfsPackDescription#getMaxUpdateIndex()}
* as the primary key identifier for a
* {@link org.eclipse.jgit.internal.storage.pack.PackExt#REFTABLE} only pack
* description, ensuring that when there are competing transactions one wins,
* and one will fail.
*/
public class DfsReftableDatabase extends DfsRefDatabase {
final ReftableDatabase reftableDatabase;
private DfsReader ctx;
private DfsReftableStack stack;
/**
* Initialize the reference database for a repository.
*
* @param repo
* the repository this database instance manages references for.
*/
protected DfsReftableDatabase(DfsRepository repo) {
super(repo);
reftableDatabase = new ReftableDatabase() {
@Override
public MergedReftable openMergedReftable() throws IOException {
Lock l = DfsReftableDatabase.this.getLock();
l.lock();
try {
return new MergedReftable(stack().readers());
} finally {
l.unlock();
}
}
};
stack = null;
}
/** {@inheritDoc} */
@Override
public boolean hasVersioning() {
return true;
}
/** {@inheritDoc} */
@Override
public boolean performsAtomicTransactions() {
return true;
}
/** {@inheritDoc} */
@Override
public BatchRefUpdate newBatchUpdate() {
DfsObjDatabase odb = getRepository().getObjectDatabase();
return new DfsReftableBatchRefUpdate(this, odb);
}
/**
* Get configuration to write new reftables with.
*
* @return configuration to write new reftables with.
*/
public ReftableConfig getReftableConfig() {
return new ReftableConfig(getRepository());
}
/**
* Get the lock protecting this instance's state.
*
* @return the lock protecting this instance's state.
*/
protected ReentrantLock getLock() {
return reftableDatabase.getLock();
}
/**
* Whether to compact reftable instead of extending the stack depth.
*
* @return {@code true} if commit of a new small reftable should try to
* replace a prior small reftable by performing a compaction,
* instead of extending the stack depth.
*/
protected boolean compactDuringCommit() {
return true;
}
/**
* Obtain a handle to the stack of reftables. Must hold lock.
*
* @return (possibly cached) handle to the stack.
* @throws java.io.IOException
* if tables cannot be opened.
*/
protected DfsReftableStack stack() throws IOException {
if (!getLock().isLocked()) {
throw new IllegalStateException("most hold lock to access stack"); //$NON-NLS-1$
}
DfsObjDatabase odb = getRepository().getObjectDatabase();
if (ctx == null) {
ctx = odb.newReader();
}
if (stack == null) {
stack = DfsReftableStack.open(ctx, Arrays.asList(odb.getReftables()));
}
return stack;
}
@Override
public boolean isNameConflicting(String refName) throws IOException {
return reftableDatabase.isNameConflicting(refName, new TreeSet<>(), new HashSet<>());
}
/** {@inheritDoc} */
@Override
public Ref exactRef(String name) throws IOException {
return reftableDatabase.exactRef(name);
}
/** {@inheritDoc} */
@Override
public Map