package com.beijunyi.parallelgit.filesystem;
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.ClosedFileSystemException;
import javax.annotation.Nonnull;
import com.beijunyi.parallelgit.utils.BlobUtils;
import com.beijunyi.parallelgit.utils.io.*;
import org.eclipse.jgit.lib.*;
import static org.eclipse.jgit.lib.Constants.*;
public class GfsObjectService implements Closeable {
private final Repository repo;
private final ObjectReader reader;
private final ObjectInserter inserter;
private volatile boolean closed = false;
GfsObjectService(final Repository repo) {
this.repo = repo;
this.reader = repo.newObjectReader();
this.inserter = repo.newObjectInserter();
}
@Nonnull
public Repository getRepository() {
return repo;
}
@Nonnull
public ObjectLoader open(AnyObjectId objectId) throws IOException {
checkClosed();
synchronized(reader) {
return reader.open(objectId);
}
}
public boolean hasObject(AnyObjectId objectId) throws IOException {
checkClosed();
synchronized(reader) {
return reader.has(objectId);
}
}
@Nonnull
public <S extends ObjectSnapshot> S read(ObjectId id, Class<S> type) throws IOException {
if(BlobSnapshot.class.isAssignableFrom(type))
return type.cast(readBlob(id));
if(TreeSnapshot.class.isAssignableFrom(type))
return type.cast(readTree(id));
throw new UnsupportedOperationException(type.getName());
}
@Nonnull
public BlobSnapshot readBlob(ObjectId id) throws IOException {
checkClosed();
synchronized(reader) {
return BlobUtils.readBlob(id, reader);
}
}
public long getBlobSize(ObjectId id) throws IOException {
checkClosed();
synchronized(reader) {
return BlobUtils.getBlobSize(id, reader);
}
}
@Nonnull
public TreeSnapshot readTree(ObjectId id) throws IOException {
checkClosed();
synchronized(reader) {
return TreeSnapshot.load(id, reader);
}
}
@Nonnull
public ObjectId write(ObjectSnapshot snapshot) throws IOException {
return snapshot.save(inserter);
}
public void pullObject(ObjectId id, boolean flush, GfsObjectService sourceObjService) throws IOException {
if(!hasObject(id)) {
ObjectLoader loader = sourceObjService.open(id);
switch(loader.getType()) {
case OBJ_TREE:
pullTree(id, sourceObjService);
break;
case OBJ_BLOB:
pullBlob(id, sourceObjService);
break;
default:
throw new UnsupportedOperationException(id.toString());
}
if(flush) flush();
}
}
public void pullObject(ObjectId id, GfsObjectService sourceObjService) throws IOException {
pullObject(id, true, sourceObjService);
}
public void flush() throws IOException {
checkClosed();
synchronized(inserter) {
inserter.flush();
}
}
@Override
public synchronized void close() {
if(!closed) {
closed = true;
reader.close();
inserter.close();
repo.close();
}
}
private void pullTree(ObjectId id, GfsObjectService sourceObjService) throws IOException {
TreeSnapshot tree = sourceObjService.readTree(id);
for(GitFileEntry entry : tree.getData().values())
pullObject(entry.getId(), false, sourceObjService);
write(tree);
}
private void pullBlob(ObjectId id, GfsObjectService sourceObjService) throws IOException {
write(sourceObjService.readBlob(id));
}
private void checkClosed() {
if(closed) throw new ClosedFileSystemException();
}
}