notifyAll();
}
prb.remove(BulkTransmitter.this);
if(logMINOR)
Logger.minor(this, "Failed to send "+uid+": peer restarted: "+peer);
throw new DisconnectedException();
}
synchronized(this) {
if(finished) return true;
if(cancelled) return false;
blockNo = blocksNotSentButPresent.firstOne();
}
if(blockNo < 0) {
setAllQueued();
if(noWait && prb.hasWholeFile()) {
completed();
return true;
}
synchronized(this) {
// Wait for all packets to complete
while(true) {
if(failedPacket) {
cancel("Packet send failed");
return false;
}
if(logMINOR)
Logger.minor(this, "Waiting for packets: remaining: "+inFlightPackets);
if(inFlightPackets == 0) break;
try {
wait();
if(failedPacket) {
cancel("Packet send failed");
return false;
}
if(inFlightPackets == 0) break;
continue outer; // Might be a packet...
} catch (InterruptedException e) {
// Ignore
}
}
// Wait for a packet to come in, BulkReceivedAll or BulkReceiveAborted
try {
wait(SECONDS.toMillis(60));
} catch (InterruptedException e) {
// No problem
continue;
}
}
long end = System.currentTimeMillis();
if(end - lastSentPacket > TIMEOUT) {
Logger.error(this, "Send timed out on "+this);
cancel("Timeout awaiting BulkReceivedAll");
return false;
}
continue;
}
// Send a packet
byte[] buf = prb.getBlockData(blockNo);
if(buf == null) {
if(logMINOR)
Logger.minor(this, "Block "+blockNo+" is null, presumably the send is cancelled: "+this);
// Already cancelled, quit
return false;
}
// Congestion control and bandwidth limiting
try {
if(logMINOR) Logger.minor(this, "Sending packet "+blockNo);
Message msg = DMT.createFNPBulkPacketSend(uid, blockNo, buf, realTime);
UnsentPacketTag tag = new UnsentPacketTag();
peer.sendAsync(msg, tag, ctr);
synchronized(this) {
while(inFlightPackets >= max && !failedPacket)
try {
wait(1000);
} catch (InterruptedException e) {
// Ignore
}
}
synchronized(this) {
blocksNotSentButPresent.setBit(blockNo, false);
}
lastSentPacket = System.currentTimeMillis();
} catch (NotConnectedException e) {
cancel("Disconnected");
if(logMINOR)
Logger.minor(this, "Cancelled: not connected "+this);
throw new DisconnectedException();
}
}
}