package org.torrent.internal.transfer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import org.merapi.helper.handlers.BarUpdateRequestHandler;
import org.merapi.helper.messages.BarUpdateRespondMessage;
import org.torrent.internal.data.TorrentMetaInfo;
import org.torrent.internal.io.NBDataReader;
import org.torrent.internal.io.PieceVerifier;
import org.torrent.internal.peer.connection.BTConnection;
import org.torrent.internal.protocol.message.BTMessageVisitorAdapter;
import org.torrent.internal.protocol.message.BittorrentMessage;
import org.torrent.internal.protocol.message.Have;
import org.torrent.internal.protocol.message.Interested;
import org.torrent.internal.service.ContentStateListener;
import org.torrent.internal.service.event.ContentStateEvent;
import org.torrent.internal.util.BTUtil;
import org.torrent.internal.util.Validator;
public abstract class Uploader extends BTSessionListenerAdapter {
protected List<UploadSlot> slots = new ArrayList<UploadSlot>();
private final BTSession session;
private Timer timer;
public Uploader(final BTSession session, ContentWatcher watcher,
int numSlots, NBDataReader reader, TorrentMetaInfo contentInfo) {
Validator.isTrue(numSlots >= 0, "Invalid number of slots: " + numSlots);
Validator.nonNull(session, reader, contentInfo);
this.session = session;
while (numSlots-- > 0) {
slots.add(new UploadSlot(session, reader, contentInfo));
}
watcher.addContentStateListener(new ContentStateListener() {
@Override
public void requiresPiece(ContentStateEvent evt) {
}
@Override
public void verifiedPiece(ContentStateEvent evt) {
for (BTConnection con : session.getConnections()) {
if (con.isConnectionEstablished()) {
con.send(new Have(evt.getPiece().getIndex()), null);
}
}
}
@Override
public void receivedPiece(ContentStateEvent evt) {
System.out.println(evt);
}
@Override
public void stateChanged(ContentStateEvent event) {
// TODO Auto-generated method stub
}
});
timer = new Timer(true);
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
BTUtil.invokeLater(new Runnable() {
@Override
public void run() {
changeSlots();
}
});
}
}, 0, 10000);
}
public BTSession getSession() {
return session;
}
protected abstract void nextTargets(Set<BTConnection> dst);
private void changeSlots() {
Set<BTConnection> newSlots = new HashSet<BTConnection>();
nextTargets(newSlots);
for (UploadSlot slot : slots) {
BTConnection con = slot.getSlotTarget();
if (con != null && newSlots.contains(con)) {
newSlots.remove(con);
} else {
slot.setSlotTo(null);
}
}
Iterator<BTConnection> it = newSlots.iterator();
for (UploadSlot slot : slots) {
if (!it.hasNext()) {
break;
}
if (slot.getSlotTarget() == null) {
slot.setSlotTo(it.next());
}
}
}
@Override
public void receivedBTMessage(final BTConnection from,
BittorrentMessage message) {
message.accept(new BTMessageVisitorAdapter() {
@Override
public void visitInterested(Interested interested) {
for (UploadSlot slot : slots) {
if (slot.getSlotTarget() == null) {
slot.setSlotTo(from);
break;
}
}
}
});
}
@Override
public void closed() {
timer.cancel();
}
}