package the8472.bt;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import lbms.plugins.mldht.kad.utils.ThreadLocalUtils;
public class MetadataPool {
public static enum Completion {
PROGRESS,
SUCCESS,
FAILED;
}
Completion state = Completion.PROGRESS;
int length;
ByteBuffer[] buffers;
PullMetaDataConnection[] requestees;
Completion status = Completion.PROGRESS;
public MetadataPool(int length ) {
this.length = length;
int numChunks = (int) Math.ceil(length * 1.0 / (16*1024));
requestees = new PullMetaDataConnection[numChunks];
buffers = new ByteBuffer[numChunks];
}
int reservePiece(PullMetaDataConnection req) {
for(int i=0;i<requestees.length;i++) {
if(requestees[i] != null)
continue;
requestees[i] = req;
return i;
}
return -1;
}
void releasePiece(int idx) {
requestees[idx] = null;
}
void addBuffer(int idx, ByteBuffer buf) {
buffers[idx] = buf;
}
void deRegister(PullMetaDataConnection req) {
for(int i=0;i<requestees.length;i++) {
if(requestees[i] == req && buffers[i] == null)
requestees[i] = null;
}
}
void checkComletion(byte[] hash) {
if(status != Completion.PROGRESS)
return;
List<ByteBuffer> bufs = Arrays.asList(buffers);
if(bufs.stream().anyMatch(Objects::isNull)) {
return;
}
MessageDigest hasher = ThreadLocalUtils.getThreadLocalSHA1();
hasher.reset();
bufs.forEach(b -> {
b.rewind();
hasher.update(b);
});
if(Arrays.equals(hasher.digest(), hash)) {
status = Completion.SUCCESS;
return;
}
status = Completion.FAILED;
}
public Completion status() {
return status;
}
public int bytes() {
return length;
}
public ByteBuffer merge() {
if(status != Completion.SUCCESS)
throw new IllegalStateException("there is nothing to merge");
ByteBuffer buf = ByteBuffer.allocate(length);
Arrays.asList(buffers).forEach(b -> {
b.rewind();
buf.put(b);
});
buf.rewind();
return buf;
}
}