use of com.biglybt.core.peermanager.piecepicker.util.BitFlags in project BiglyBT by BiglySoftware.
the class PEPeerTransportProtocol method decodeBitfield.
protected void decodeBitfield(BTBitfield bitfield) {
received_bitfield = true;
if (is_metadata_download) {
bitfield.destroy();
return;
}
final DirectByteBuffer field = bitfield.getBitfield();
final byte[] dataf = new byte[(nbPieces + 7) / 8];
if (field.remaining(DirectByteBuffer.SS_PEER) < dataf.length) {
final String error = toString() + " has sent invalid Bitfield: too short [" + field.remaining(DirectByteBuffer.SS_PEER) + "<" + dataf.length + "]";
Debug.out(error);
if (Logger.isEnabled())
Logger.log(new LogEvent(this, LOGID, LogEvent.LT_ERROR, error));
bitfield.destroy();
return;
}
field.get(DirectByteBuffer.SS_PEER, dataf);
try {
closing_mon.enter();
if (closing)
bitfield.destroy();
else {
final BitFlags tempHavePieces;
if (peerHavePieces == null) {
tempHavePieces = new BitFlags(nbPieces);
} else {
tempHavePieces = peerHavePieces;
removeAvailability();
}
for (int i = 0; i < nbPieces; i++) {
final int index = i / 8;
final int bit = 7 - (i % 8);
final byte bData = dataf[index];
final byte b = (byte) (bData >> bit);
if ((b & 0x01) == 1) {
tempHavePieces.set(i);
manager.updateSuperSeedPiece(this, i);
}
}
bitfield.destroy();
peerHavePieces = tempHavePieces;
addAvailability();
checkSeed();
checkInterested();
checkFast(tempHavePieces);
}
} finally {
closing_mon.exit();
}
}
use of com.biglybt.core.peermanager.piecepicker.util.BitFlags in project BiglyBT by BiglySoftware.
the class PercentHaveWeNeedItem method refresh.
@Override
public void refresh(TableCell cell) {
PEPeer peer = (PEPeer) cell.getDataSource();
int value = -1;
if (peer != null) {
PEPeerManager pm = peer.getManager();
if (pm != null) {
if (!pm.isSeeding()) {
if (peer.isSeed()) {
value = 1000 - pm.getDiskManager().getPercentDoneExcludingDND();
} else {
BitFlags bf = peer.getAvailable();
if (bf != null) {
boolean[] peer_has = bf.flags;
if (peer_has != null) {
int we_have = 0;
int we_need = 0;
int they_have_we_need = 0;
DiskManagerPiece[] dm_pieces = pm.getDiskManager().getPieces();
for (int i = 0; i < dm_pieces.length; i++) {
DiskManagerPiece piece = dm_pieces[i];
if (piece.isNeeded()) {
if (piece.isDone()) {
we_have++;
} else {
we_need++;
if (peer_has[i]) {
they_have_we_need++;
}
}
}
}
if (we_need > 0) {
value = (1000 * they_have_we_need) / (we_have + we_need);
}
}
}
}
}
}
}
if (!cell.setSortValue(value) && cell.isValid()) {
return;
}
cell.setText(value < 0 ? "" : DisplayFormatters.formatPercentFromThousands(value));
}
use of com.biglybt.core.peermanager.piecepicker.util.BitFlags in project BiglyBT by BiglySoftware.
the class PeerInfoView method refreshInfoCanvas.
/**
* Constructs and image representing the download state of _all_
* the pieces in the torrent. Particularily slow when there's lots of pieces,
* and also wasteful since only a fraction of them ever get painted at
* any given time.
*
* TODO: Construct image for visible area only or something
*/
private void refreshInfoCanvas() {
refreshInfoCanvasQueued = false;
if (peerInfoComposite == null || peerInfoComposite.isDisposed() || !peerInfoComposite.isVisible()) {
return;
}
peerInfoCanvas.layout(true);
Rectangle bounds = peerInfoCanvas.getClientArea();
if (bounds.width <= 0 || bounds.height <= 0)
return;
if (img != null && !img.isDisposed()) {
img.dispose();
img = null;
}
if (peer == null || peer.getPeerState() != PEPeer.TRANSFERING) {
GC gc = new GC(peerInfoCanvas);
gc.fillRectangle(bounds);
gc.dispose();
return;
}
PEPeerManager pm = peer.getManager();
DiskManager dm = pm == null ? null : pm.getDiskManager();
BitFlags peerHavePieces = peer.getAvailable();
if (dm == null || peerHavePieces == null) {
GC gc = new GC(peerInfoCanvas);
gc.fillRectangle(bounds);
gc.dispose();
return;
}
int numPieces = dm.getNbPieces();
if (numPieces > MAX_PIECES_TO_SHOW) {
numPieces = MAX_PIECES_TO_SHOW;
}
DiskManagerPiece[] dm_pieces = dm.getPieces();
int iNumCols = bounds.width / BLOCK_SIZE;
int iNeededHeight = (((numPieces - 1) / iNumCols) + 1) * BLOCK_SIZE;
if (sc.getMinHeight() != iNeededHeight) {
sc.setMinHeight(iNeededHeight);
sc.layout(true, true);
bounds = peerInfoCanvas.getClientArea();
}
img = new Image(peerInfoCanvas.getDisplay(), bounds.width, iNeededHeight);
GC gcImg = new GC(img);
try {
// use advanced capabilities for faster drawText
gcImg.setAdvanced(true);
gcImg.setBackground(peerInfoCanvas.getBackground());
gcImg.fillRectangle(0, 0, bounds.width, iNeededHeight);
int[] availability = pm.getAvailability();
int iNextDLPieceID = -1;
int iDLPieceID = -1;
int[] ourRequestedPieces = peer.getOutgoingRequestedPieceNumbers();
if (ourRequestedPieces != null) {
if (!peer.isChokingMe()) {
if (ourRequestedPieces.length > 0) {
iDLPieceID = ourRequestedPieces[0];
if (ourRequestedPieces.length > 1)
iNextDLPieceID = ourRequestedPieces[1];
}
} else {
if (ourRequestedPieces.length > 0)
iNextDLPieceID = ourRequestedPieces[0];
}
// if (iNextDLPieceID == -1) {
// iNextDLPieceID = peer.getNextPieceNumberGuess();
// }
}
int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers();
if (peerRequestedPieces == null)
peerRequestedPieces = new int[0];
int peerNextRequestedPiece = -1;
if (peerRequestedPieces.length > 0)
peerNextRequestedPiece = peerRequestedPieces[0];
Arrays.sort(peerRequestedPieces);
int iRow = 0;
int iCol = 0;
for (int i = 0; i < numPieces; i++) {
int colorIndex;
boolean done = (dm_pieces == null) ? false : dm_pieces[i].isDone();
int iXPos = iCol * BLOCK_SIZE;
int iYPos = iRow * BLOCK_SIZE;
if (done) {
if (peerHavePieces.flags[i])
colorIndex = BLOCKCOLOR_AVAIL_HAVE;
else
colorIndex = BLOCKCOLOR_NOAVAIL_HAVE;
gcImg.setBackground(blockColors[colorIndex]);
gcImg.fillRectangle(iXPos, iYPos, BLOCK_FILLSIZE, BLOCK_FILLSIZE);
} else {
// !done
boolean partiallyDone = (dm_pieces == null) ? false : dm_pieces[i].getNbWritten() > 0;
int x = iXPos;
int width = BLOCK_FILLSIZE;
if (partiallyDone) {
if (peerHavePieces.flags[i])
colorIndex = BLOCKCOLOR_AVAIL_HAVE;
else
colorIndex = BLOCKCOLOR_NOAVAIL_HAVE;
gcImg.setBackground(blockColors[colorIndex]);
// partiallyDone false when dm_pieces null
@SuppressWarnings("null") int iNewWidth = (int) (((float) dm_pieces[i].getNbWritten() / dm_pieces[i].getNbBlocks()) * width);
if (iNewWidth >= width)
iNewWidth = width - 1;
else if (iNewWidth <= 0)
iNewWidth = 1;
gcImg.fillRectangle(x, iYPos, iNewWidth, BLOCK_FILLSIZE);
width -= iNewWidth;
x += iNewWidth;
}
if (peerHavePieces.flags[i])
colorIndex = BLOCKCOLOR_AVAIL_NOHAVE;
else
colorIndex = BLOCKCOLOR_NOAVAIL_NOHAVE;
gcImg.setBackground(blockColors[colorIndex]);
gcImg.fillRectangle(x, iYPos, width, BLOCK_FILLSIZE);
}
// Down Arrow inside box for "dowloading" piece
if (i == iDLPieceID) {
gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]);
gcImg.fillPolygon(new int[] { iXPos, iYPos, iXPos + BLOCK_FILLSIZE, iYPos, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE });
}
// Small Down Arrow inside box for next download piece
if (i == iNextDLPieceID) {
gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]);
gcImg.fillPolygon(new int[] { iXPos + 2, iYPos + 2, iXPos + BLOCK_FILLSIZE - 1, iYPos + 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + BLOCK_FILLSIZE - 1 });
}
// Up Arrow in uploading piece
if (i == peerNextRequestedPiece) {
gcImg.setBackground(blockColors[BLOCKCOLOR_TRANSFER]);
gcImg.fillPolygon(new int[] { iXPos, iYPos + BLOCK_FILLSIZE, iXPos + BLOCK_FILLSIZE, iYPos + BLOCK_FILLSIZE, iXPos + (BLOCK_FILLSIZE / 2), iYPos });
} else if (Arrays.binarySearch(peerRequestedPieces, i) >= 0) {
// Small Up Arrow each upload request
gcImg.setBackground(blockColors[BLOCKCOLOR_NEXT]);
gcImg.fillPolygon(new int[] { iXPos + 1, iYPos + BLOCK_FILLSIZE - 2, iXPos + BLOCK_FILLSIZE - 2, iYPos + BLOCK_FILLSIZE - 2, iXPos + (BLOCK_FILLSIZE / 2), iYPos + 2 });
}
if (availability != null && availability[i] < 10) {
gcImg.setFont(font);
String sNumber = String.valueOf(availability[i]);
Point size = gcImg.stringExtent(sNumber);
int x = iXPos + (BLOCK_FILLSIZE / 2) - (size.x / 2);
int y = iYPos + (BLOCK_FILLSIZE / 2) - (size.y / 2);
gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
gcImg.drawText(sNumber, x, y, true);
}
iCol++;
if (iCol >= iNumCols) {
iCol = 0;
iRow++;
}
}
} catch (Exception e) {
Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e));
} finally {
gcImg.dispose();
}
peerInfoCanvas.redraw();
}
use of com.biglybt.core.peermanager.piecepicker.util.BitFlags in project BiglyBT by BiglySoftware.
the class RemotePieceDistributionView method refresh.
@Override
public void refresh() {
if (pem == null)
return;
if (peer instanceof PEPeerTransportProtocol) {
PEPeerTransportProtocol pet = (PEPeerTransportProtocol) peer;
BitFlags avl = pet.getAvailable();
if (avl == null)
hasPieces = null;
else
hasPieces = avl.flags;
} else {
if (peer.isSeed()) {
hasPieces = new boolean[pem.getPieces().length];
Arrays.fill(hasPieces, true);
} else
hasPieces = null;
}
super.refresh();
}
use of com.biglybt.core.peermanager.piecepicker.util.BitFlags in project BiglyBT by BiglySoftware.
the class PiecePickerImpl method findRTAPieceToDownload.
protected final boolean findRTAPieceToDownload(PEPeerTransport pt, boolean best_uploader, long best_uploader_next_block_eta) {
if (pt == null || pt.getPeerState() != PEPeer.TRANSFERING) {
return (false);
}
final BitFlags peerHavePieces = pt.getAvailable();
if (peerHavePieces == null || peerHavePieces.nbSet <= 0) {
return (false);
}
String rta_log_str = LOG_RTA ? pt.getIp() : null;
try {
// how many KB/s has the peer has been sending
final int peerSpeed = (int) pt.getStats().getDataReceiveRate() / 1024;
final int startI = peerHavePieces.start;
final int endI = peerHavePieces.end;
int piece_min_rta_index = -1;
int piece_min_rta_block = 0;
long piece_min_rta_time = Long.MAX_VALUE;
long now = SystemTime.getCurrentTime();
long my_next_block_eta = now + getNextBlockETAFromNow(pt);
for (int i = startI; i <= endI; i++) {
long piece_rta = provider_piece_rtas[i];
if (peerHavePieces.flags[i] && startPriorities[i] == PRIORITY_REALTIME && piece_rta > 0) {
final DiskManagerPiece dmPiece = dmPieces[i];
if (!dmPiece.isDownloadable()) {
continue;
}
final PEPiece pePiece = pePieces[i];
if (pePiece != null && pePiece.isDownloaded()) {
continue;
}
Object realtime_data = null;
boolean try_allocate_even_though_late = my_next_block_eta > piece_rta && best_uploader_next_block_eta > piece_rta;
if (piece_rta >= piece_min_rta_time) {
// piece is less urgent than an already found one
} else if (my_next_block_eta > piece_rta && !(best_uploader || best_uploader_next_block_eta > piece_rta)) {
// only allocate if we have a chance of getting this block in time or we're
// the best uploader we've got/even the best uploader can't get it
// the second part is important for when we get to the point whereby no peers
// can get a block in time. Here we need to allocate someone to get it as
// otherwise we'll concentrate on getting lower priority pieces that we can
// get in time and leave the stuck ones for just the best uploader to get
} else if (pePiece == null || (realtime_data = pePiece.getRealTimeData()) == null) {
if (LOG_RTA)
rta_log_str += "{alloc_new=" + i + ",time=" + (piece_rta - now) + "}";
// no real-time block allocated yet
piece_min_rta_time = piece_rta;
piece_min_rta_index = i;
piece_min_rta_block = 0;
} else {
RealTimeData rtd = (RealTimeData) realtime_data;
// check the blocks to see if any are now lagging behind their ETA given current peer speed
List[] peer_requests = rtd.getRequests();
for (int j = 0; j < peer_requests.length; j++) {
if (pePiece.isDownloaded(j) || pePiece.isWritten(j)) {
continue;
}
List block_peer_requests = peer_requests[j];
long best_eta = Long.MAX_VALUE;
boolean pt_already_present = false;
// tidy up existing request data
Iterator it = block_peer_requests.iterator();
while (it.hasNext()) {
RealTimePeerRequest pr = (RealTimePeerRequest) it.next();
PEPeerTransport this_pt = pr.getPeer();
if (this_pt.getPeerState() != PEPeer.TRANSFERING) {
if (LOG_RTA)
rta_log_str += "{peer_dead=" + this_pt.getIp() + "}";
it.remove();
continue;
}
DiskManagerReadRequest this_request = pr.getRequest();
int request_index = this_pt.getRequestIndex(this_request);
if (request_index == -1) {
if (LOG_RTA)
rta_log_str += "{request_lost=" + this_request.getPieceNumber() + "}";
it.remove();
continue;
}
if (this_pt == pt) {
pt_already_present = true;
break;
}
long this_up_bps = this_pt.getStats().getDataReceiveRate();
if (this_up_bps < 1) {
this_up_bps = 1;
}
int next_block_bytes = (request_index + 1) * DiskManager.BLOCK_SIZE;
long this_peer_eta = now + ((next_block_bytes * 1000) / this_up_bps);
best_eta = Math.min(best_eta, this_peer_eta);
}
if (!pt_already_present) {
if (block_peer_requests.size() == 0) {
if (LOG_RTA)
rta_log_str += "{alloc as no req=" + i + ",block=" + j + ",time=" + (piece_rta - now) + "}";
piece_min_rta_time = piece_rta;
piece_min_rta_index = i;
piece_min_rta_block = j;
// earlier blocks always have priority
break;
} else if (best_eta > piece_rta && (best_uploader || !try_allocate_even_though_late)) {
if (LOG_RTA)
rta_log_str += "{lagging=" + i + ",block=" + j + ",time=" + (best_eta - piece_rta) + "}";
if (my_next_block_eta < best_eta) {
if (LOG_RTA)
rta_log_str += "{taking over, time=" + (best_eta - my_next_block_eta) + "}";
piece_min_rta_time = piece_rta;
piece_min_rta_index = i;
piece_min_rta_block = j;
// earlier blocks always have priority
break;
}
}
}
}
}
}
}
if (piece_min_rta_index != -1) {
if (LOG_RTA)
rta_log_str += ",{select_piece=" + piece_min_rta_index + ",block=" + piece_min_rta_block + ",time=" + (piece_min_rta_time - now) + "}";
if (dispenser.dispense(1, DiskManager.BLOCK_SIZE) == 1 || (pt.isLANLocal() && !includeLanPeersInReqLimiting)) {
PEPiece pePiece = pePieces[piece_min_rta_index];
if (pePiece == null) {
// create piece manually
pePiece = new PEPieceImpl(this, dmPieces[piece_min_rta_index], peerSpeed >> 1);
// Assign the created piece to the pieces array.
peerControl.addPiece(pePiece, piece_min_rta_index, pt);
pePiece.setResumePriority(PRIORITY_REALTIME);
if (availability[piece_min_rta_index] <= globalMinOthers) {
nbRarestActive++;
}
}
RealTimeData rtd = (RealTimeData) pePiece.getRealTimeData();
if (rtd == null) {
rtd = new RealTimeData(pePiece);
pePiece.setRealTimeData(rtd);
}
pePiece.getAndMarkBlock(pt, piece_min_rta_block);
DiskManagerReadRequest request = pt.request(piece_min_rta_index, piece_min_rta_block * DiskManager.BLOCK_SIZE, pePiece.getBlockSize(piece_min_rta_block), true);
if (request != null) {
List real_time_requests = rtd.getRequests()[piece_min_rta_block];
real_time_requests.add(new RealTimePeerRequest(pt, request));
pt.setLastPiece(piece_min_rta_index);
pePiece.setLastRequestedPeerSpeed(peerSpeed);
return (true);
} else {
if (LOG_RTA)
rta_log_str += "{request failed}";
if (!pt.isLANLocal() || includeLanPeersInReqLimiting)
dispenser.returnUnusedChunks(1, DiskManager.BLOCK_SIZE);
return (false);
}
} else {
if (LOG_RTA)
rta_log_str += "{dispenser denied}";
return (false);
}
} else {
if (LOG_RTA)
rta_log_str += "{no piece found}";
return (false);
}
} finally {
if (LOG_RTA) {
System.out.println(rta_log_str);
}
}
}
Aggregations