use of com.biglybt.core.disk.impl.piecemapper.DMPieceList in project BiglyBT by BiglySoftware.
the class DMWriterImpl method writeBlock.
@Override
public void writeBlock(final DiskManagerWriteRequest request, final DiskManagerWriteRequestListener _listener) {
request.requestStarts();
final DiskManagerWriteRequestListener listener = new DiskManagerWriteRequestListener() {
@Override
public void writeCompleted(DiskManagerWriteRequest request) {
request.requestEnds(true);
_listener.writeCompleted(request);
}
@Override
public void writeFailed(DiskManagerWriteRequest request, Throwable cause) {
request.requestEnds(false);
_listener.writeFailed(request, cause);
}
};
try {
int pieceNumber = request.getPieceNumber();
DirectByteBuffer buffer = request.getBuffer();
int offset = request.getOffset();
// Do not allow to write in a piece marked as done. we can get here if
final DiskManagerPiece dmPiece = disk_manager.getPieces()[pieceNumber];
if (dmPiece.isDone()) {
// Debug.out( "write: piece already done (" + request.getPieceNumber() + "/" + request.getOffset());
buffer.returnToPool();
// XXX: no writing was done; is this neccesary for complete()?
listener.writeCompleted(request);
} else {
int buffer_position = buffer.position(DirectByteBuffer.SS_DW);
int buffer_limit = buffer.limit(DirectByteBuffer.SS_DW);
// final long write_length = buffer_limit - buffer_position;
int previousFilesLength = 0;
int currentFile = 0;
DMPieceList pieceList = disk_manager.getPieceList(pieceNumber);
DMPieceMapEntry current_piece = pieceList.get(currentFile);
long fileOffset = current_piece.getOffset();
while ((previousFilesLength + current_piece.getLength()) < offset) {
previousFilesLength += current_piece.getLength();
currentFile++;
fileOffset = 0;
current_piece = pieceList.get(currentFile);
}
List chunks = new ArrayList();
while (buffer_position < buffer_limit) {
current_piece = pieceList.get(currentFile);
long file_limit = buffer_position + ((current_piece.getFile().getLength() - current_piece.getOffset()) - (offset - previousFilesLength));
if (file_limit > buffer_limit) {
file_limit = buffer_limit;
}
if (file_limit > buffer_position) {
long file_pos = fileOffset + (offset - previousFilesLength);
chunks.add(new Object[] { current_piece.getFile(), new Long(file_pos), new Integer((int) file_limit) });
buffer_position = (int) file_limit;
}
currentFile++;
fileOffset = 0;
previousFilesLength = offset;
}
DiskManagerWriteRequestListener l = new DiskManagerWriteRequestListener() {
@Override
public void writeCompleted(DiskManagerWriteRequest request) {
complete();
listener.writeCompleted(request);
}
@Override
public void writeFailed(DiskManagerWriteRequest request, Throwable cause) {
complete();
if (dmPiece.isDone()) {
if (Logger.isEnabled()) {
Logger.log(new LogEvent(disk_manager, LOGID, "Piece " + dmPiece.getPieceNumber() + " write failed but already marked as done"));
}
listener.writeCompleted(request);
} else {
disk_manager.setFailed("Disk write error - " + Debug.getNestedExceptionMessage(cause));
Debug.printStackTrace(cause);
listener.writeFailed(request, cause);
}
}
protected void complete() {
try {
this_mon.enter();
async_writes--;
if (!write_requests.remove(request)) {
Debug.out("request not found");
}
if (stopped) {
async_write_sem.release();
}
} finally {
this_mon.exit();
}
}
};
try {
this_mon.enter();
if (stopped) {
buffer.returnToPool();
listener.writeFailed(request, new Exception("Disk writer has been stopped"));
return;
} else {
async_writes++;
write_requests.add(request);
}
} finally {
this_mon.exit();
}
new requestDispatcher(request, l, buffer, chunks);
}
} catch (Throwable e) {
request.getBuffer().returnToPool();
disk_manager.setFailed("Disk write error - " + Debug.getNestedExceptionMessage(e));
Debug.printStackTrace(e);
listener.writeFailed(request, e);
}
}
use of com.biglybt.core.disk.impl.piecemapper.DMPieceList in project BiglyBT by BiglySoftware.
the class PiecePickerImpl method computeBasePriorities.
/**
* This computes the base priority for all pieces that need requesting if there's
* been any availability change or user priority setting changes since the last
* call, which will be most of the time since availability changes so dynamicaly
* It will change startPriorities[] (unless there was nothing to do)
*/
private void computeBasePriorities() {
final long now = SystemTime.getCurrentTime();
if (now < lastProviderRecalcTime || now - lastProviderRecalcTime > 1000) {
lastProviderRecalcTime = now;
priorityRTAexists = computeProviderPriorities();
}
if (!priorityRTAexists) {
if (startPriorities != null && ((now > timeLastPriorities && now < timeLastPriorities + TIME_MIN_PRIORITIES) || (priorityParamChange >= paramPriorityChange && priorityFileChange >= filePriorityChange && priorityAvailChange >= availabilityChange))) {
// *somehow* nothing changed, so nothing to do
return;
}
}
// store the latest change indicators before we start making dependent calculations so that a
// further change while computing stuff doesn't get lost
timeLastPriorities = now;
priorityParamChange = paramPriorityChange;
priorityFileChange = filePriorityChange;
priorityAvailChange = availabilityChange;
boolean foundPieceToDownload = false;
final int[] newPriorities = new int[nbPieces];
// locals are a tiny bit faster
final boolean firstPiecePriorityL = firstPiecePriority;
final boolean completionPriorityL = completionPriority;
final DMPieceMap pieceMap = diskManager.getPieceMap();
CopyOnWriteSet<Integer> forced = forced_pieces;
try {
final boolean rarestOverride = calcRarestAllowed() < 1;
// calculate all base (starting) priorities for all pieces needing requesting
final int nbConnects = peerControl.getNbPeers() + peerControl.getNbSeeds();
for (int i = 0; i < nbPieces; i++) {
final DiskManagerPiece dmPiece = dmPieces[i];
if (dmPiece.isDone()) {
if (forced != null && forced.contains(i)) {
if (forced.remove(i) && forced.size() == 0) {
synchronized (this) {
if (forced_pieces != null && forced_pieces.size() == 0) {
forced_pieces = null;
}
}
}
}
// nothing to do for pieces not needing requesting
continue;
}
int startPriority = Integer.MIN_VALUE;
final DMPieceList pieceList = pieceMap.getPieceList(dmPiece.getPieceNumber());
final int pieceListSize = pieceList.size();
for (int j = 0; j < pieceListSize; j++) {
final DiskManagerFileInfoImpl fileInfo = pieceList.get(j).getFile();
final long downloaded = fileInfo.getDownloaded();
final long length = fileInfo.getLength();
if (length > 0 && downloaded < length && !fileInfo.isSkipped()) {
int priority = 0;
// user option "prioritize first and last piece"
// TODO: should prioritize ~10% from edges of file
boolean hasFirstLastPriority = false;
if (firstPiecePriorityL && fileInfo.getNbPieces() > FIRST_PIECE_MIN_NB) {
if (i == fileInfo.getFirstPieceNumber() || i == fileInfo.getLastPieceNumber()) {
hasFirstLastPriority = true;
}
}
// if the file is high-priority
// startPriority +=(1000 *fileInfo.getPriority()) /255;
int file_priority = fileInfo.getPriority();
int max = Math.max(file_priority, max_file_priority);
int min = Math.min(file_priority, min_file_priority);
int range = max - min;
if (range > 0) {
int relative_file_priority = file_priority - min;
priority += PRIORITY_W_FILE_BASE;
int adjustment;
if (hasFirstLastPriority) {
// one less than the next higher priority file
adjustment = ((PRIORITY_W_FILE_RANGE * (relative_file_priority + 1)) / range) - 1;
} else {
adjustment = (PRIORITY_W_FILE_RANGE * relative_file_priority) / range;
}
priority += adjustment;
} else {
if (hasFirstLastPriority) {
priority += PRIORITY_W_FIRSTLAST;
}
}
if (completionPriorityL) {
final long percent = (1000 * downloaded) / length;
if (percent >= 900) {
priority += (PRIORITY_W_COMPLETION * downloaded) / diskManager.getTotalLength();
}
}
if (priority > startPriority) {
startPriority = priority;
}
}
}
if (startPriority >= 0) {
dmPiece.setNeeded();
foundPieceToDownload = true;
final int avail = availability[i];
// nbconnects is async calculate so may be wrong - make sure we don't decrease pri by accident
if (avail > 0 && nbConnects > avail) {
// boost priority for rarity
startPriority += nbConnects - avail;
// Boost priority even a little more if it's a globally rarest piece
if (!rarestOverride && avail <= globalMinOthers)
startPriority += nbConnects / avail;
}
if (provider_piece_rtas != null) {
if (provider_piece_rtas[i] > 0) {
startPriority = PRIORITY_REALTIME;
}
} else if (provider_piece_priorities != null) {
startPriority += provider_piece_priorities[i];
} else if (forced != null && forced.contains(i)) {
startPriority = PRIORITY_FORCED;
}
} else {
dmPiece.clearNeeded();
}
newPriorities[i] = startPriority;
}
} catch (Throwable e) {
Debug.printStackTrace(e);
}
if (sequentialDownload != 0 && !priorityRTAexists) {
int seq_pri = PRIORITY_SEQUENTIAL_START;
boolean do_file_priorities = min_file_priority != max_file_priority;
int file_priority_start = nbPieces * 10;
int loop_start;
int loop_end;
int loop_dir;
if (sequentialDownload > 0) {
loop_start = nbPieces;
loop_end = sequentialDownload - 1;
loop_dir = -1;
} else {
loop_start = -1;
loop_end = -(sequentialDownload + 1);
loop_dir = +1;
}
int loop_pos = loop_start;
do {
loop_pos += loop_dir;
int priority = newPriorities[loop_pos];
if (priority == Integer.MIN_VALUE) {
continue;
}
if (priority != PRIORITY_FORCED) {
if (do_file_priorities) {
final DiskManagerPiece dmPiece = dmPieces[loop_pos];
int highest = Integer.MIN_VALUE;
final DMPieceList pieceList = pieceMap.getPieceList(dmPiece.getPieceNumber());
final int pieceListSize = pieceList.size();
for (int j = 0; j < pieceListSize; j++) {
final DiskManagerFileInfoImpl fileInfo = pieceList.get(j).getFile();
final long downloaded = fileInfo.getDownloaded();
final long length = fileInfo.getLength();
if (length > 0 && downloaded < length && !fileInfo.isSkipped()) {
highest = Math.max(highest, fileInfo.getPriority());
}
}
if (highest == Integer.MIN_VALUE) {
newPriorities[loop_pos] = seq_pri;
} else {
int rel = highest - min_file_priority;
newPriorities[loop_pos] = file_priority_start + nbPieces * rel + seq_pri;
}
} else {
newPriorities[loop_pos] = seq_pri;
}
}
seq_pri += 10;
} while (loop_pos != loop_end);
}
if (foundPieceToDownload != hasNeededUndonePiece) {
hasNeededUndonePiece = foundPieceToDownload;
neededUndonePieceChange++;
}
startPriorities = newPriorities;
}
use of com.biglybt.core.disk.impl.piecemapper.DMPieceList in project BiglyBT by BiglySoftware.
the class FilesItem method refresh.
@Override
public void refresh(TableCell cell) {
PEPiece pePiece = (PEPiece) cell.getDataSource();
String value = "";
if (pePiece != null) {
DiskManagerPiece dmp = pePiece.getDMPiece();
if (dmp != null) {
DMPieceList l = dmp.getManager().getPieceList(pePiece.getPieceNumber());
for (int i = 0; i < l.size(); i++) {
DMPieceMapEntry entry = l.get(i);
String name = entry.getFile().getTorrentFile().getRelativePath();
value += (value.isEmpty() ? "" : "; ") + name;
}
}
}
if (!cell.setSortValue(value) && cell.isValid())
return;
cell.setText(value);
}
use of com.biglybt.core.disk.impl.piecemapper.DMPieceList in project BiglyBT by BiglySoftware.
the class PieceInfoView method refreshInfoCanvas.
protected void refreshInfoCanvas() {
synchronized (PieceInfoView.this) {
alreadyFilling = false;
}
if (pieceInfoCanvas == null || pieceInfoCanvas.isDisposed() || !pieceInfoCanvas.isVisible()) {
return;
}
pieceInfoCanvas.layout(true);
Rectangle bounds = pieceInfoCanvas.getClientArea();
if (bounds.width <= 0 || bounds.height <= 0) {
topLabelLHS = "";
updateTopLabel();
return;
}
if (dlm == null) {
GC gc = new GC(pieceInfoCanvas);
gc.fillRectangle(bounds);
gc.dispose();
topLabelLHS = MessageText.getString("view.one.download.only");
topLabelRHS = "";
updateTopLabel();
return;
}
PEPeerManager pm = dlm.getPeerManager();
DiskManager dm = dlm.getDiskManager();
if (pm == null || dm == null) {
GC gc = new GC(pieceInfoCanvas);
gc.fillRectangle(bounds);
gc.dispose();
topLabelLHS = "";
updateTopLabel();
return;
}
int iNumCols = bounds.width / BLOCK_SIZE;
int iNeededHeight = (((dm.getNbPieces() - 1) / iNumCols) + 1) * BLOCK_SIZE;
if (img != null && !img.isDisposed()) {
Rectangle imgBounds = img.getBounds();
if (imgBounds.width != bounds.width || imgBounds.height != iNeededHeight) {
oldBlockInfo = null;
img.dispose();
img = null;
}
}
DiskManagerPiece[] dm_pieces = dm.getPieces();
PEPiece[] currentDLPieces = pm.getPieces();
byte[] uploadingPieces = new byte[dm_pieces.length];
// find upload pieces
for (PEPeer peer : pm.getPeers()) {
int[] peerRequestedPieces = peer.getIncomingRequestedPieceNumbers();
if (peerRequestedPieces != null && peerRequestedPieces.length > 0) {
int pieceNum = peerRequestedPieces[0];
if (uploadingPieces[pieceNum] < 2)
uploadingPieces[pieceNum] = 2;
for (int j = 1; j < peerRequestedPieces.length; j++) {
pieceNum = peerRequestedPieces[j];
if (uploadingPieces[pieceNum] < 1)
uploadingPieces[pieceNum] = 1;
}
}
}
if (sc.getMinHeight() != iNeededHeight) {
sc.setMinHeight(iNeededHeight);
sc.layout(true, true);
bounds = pieceInfoCanvas.getClientArea();
}
int[] availability = pm.getAvailability();
int minAvailability = Integer.MAX_VALUE;
int minAvailability2 = Integer.MAX_VALUE;
if (availability != null && availability.length > 0) {
for (int anAvailability : availability) {
if (anAvailability != 0 && anAvailability < minAvailability) {
minAvailability2 = minAvailability;
minAvailability = anAvailability;
if (minAvailability == 1) {
break;
}
}
}
}
if (img == null) {
img = new Image(pieceInfoCanvas.getDisplay(), bounds.width, iNeededHeight);
oldBlockInfo = null;
}
GC gcImg = new GC(img);
BlockInfo[] newBlockInfo = new BlockInfo[dm_pieces.length];
int iRow = 0;
try {
// use advanced capabilities for faster drawText
gcImg.setAdvanced(true);
if (oldBlockInfo == null) {
gcImg.setBackground(pieceInfoCanvas.getBackground());
gcImg.fillRectangle(0, 0, bounds.width, iNeededHeight);
}
int selectionStart = Integer.MAX_VALUE;
int selectionEnd = Integer.MIN_VALUE;
if (selectedPiece != -1) {
if (selectedPieceShowFile) {
DMPieceList l = dm.getPieceList(selectedPiece);
for (int i = 0; i < l.size(); i++) {
DMPieceMapEntry entry = l.get(i);
DiskManagerFileInfo info = entry.getFile();
int first = info.getFirstPieceNumber();
int last = info.getLastPieceNumber();
if (first < selectionStart) {
selectionStart = first;
}
if (last > selectionEnd) {
selectionEnd = last;
}
}
}
}
gcImg.setFont(font);
int iCol = 0;
for (int i = 0; i < dm_pieces.length; i++) {
if (iCol >= iNumCols) {
iCol = 0;
iRow++;
}
BlockInfo newInfo = newBlockInfo[i] = new BlockInfo();
if (i >= selectionStart && i <= selectionEnd) {
newInfo.selected = true;
}
boolean done = dm_pieces[i].isDone();
int iXPos = iCol * BLOCK_SIZE + 1;
int iYPos = iRow * BLOCK_SIZE + 1;
if (done) {
newInfo.haveWidth = BLOCK_FILLSIZE;
} else {
// !done
boolean partiallyDone = dm_pieces[i].getNbWritten() > 0;
int width = BLOCK_FILLSIZE;
if (partiallyDone) {
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;
newInfo.haveWidth = iNewWidth;
}
}
if (currentDLPieces[i] != null && currentDLPieces[i].hasUndownloadedBlock()) {
newInfo.showDown = currentDLPieces[i].getNbRequests() == 0 ? SHOW_SMALL : SHOW_BIG;
}
if (uploadingPieces[i] > 0) {
newInfo.showUp = uploadingPieces[i] < 2 ? SHOW_SMALL : SHOW_BIG;
}
if (availability != null) {
newInfo.availNum = availability[i];
if (minAvailability2 == availability[i]) {
newInfo.availDotted = true;
}
} else {
newInfo.availNum = -1;
}
if (oldBlockInfo != null && i < oldBlockInfo.length && oldBlockInfo[i].sameAs(newInfo)) {
iCol++;
continue;
}
if (newInfo.selected) {
Color fc = blockColors[BLOCKCOLOR_SHOWFILE];
gcImg.setBackground(fc);
gcImg.fillRectangle(iCol * BLOCK_SIZE, iRow * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
if (fc != file_color) {
file_color = fc;
file_color_faded = Colors.getInstance().getLighterColor(fc, 75);
}
gcImg.setBackground(file_color_faded);
gcImg.fillRectangle(iXPos + newInfo.haveWidth, iYPos, BLOCK_FILLSIZE - newInfo.haveWidth, BLOCK_FILLSIZE);
} else {
gcImg.setBackground(pieceInfoCanvas.getBackground());
gcImg.fillRectangle(iCol * BLOCK_SIZE, iRow * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
gcImg.setBackground(blockColors[BLOCKCOLOR_HAVE]);
gcImg.fillRectangle(iXPos, iYPos, newInfo.haveWidth, BLOCK_FILLSIZE);
gcImg.setBackground(blockColors[BLOCKCOLORL_NOHAVE]);
gcImg.fillRectangle(iXPos + newInfo.haveWidth, iYPos, BLOCK_FILLSIZE - newInfo.haveWidth, BLOCK_FILLSIZE);
}
if (newInfo.showDown > 0) {
drawDownloadIndicator(gcImg, iXPos, iYPos, newInfo.showDown == SHOW_SMALL);
}
if (newInfo.showUp > 0) {
drawUploadIndicator(gcImg, iXPos, iYPos, newInfo.showUp == SHOW_SMALL);
}
if (newInfo.availNum != -1) {
if (minAvailability == newInfo.availNum) {
gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1);
}
if (minAvailability2 == newInfo.availNum) {
gcImg.setLineStyle(SWT.LINE_DOT);
gcImg.setForeground(blockColors[BLOCKCOLOR_AVAILCOUNT]);
gcImg.drawRectangle(iXPos - 1, iYPos - 1, BLOCK_FILLSIZE + 1, BLOCK_FILLSIZE + 1);
gcImg.setLineStyle(SWT.LINE_SOLID);
}
String sNumber = String.valueOf(newInfo.availNum);
Point size = gcImg.stringExtent(sNumber);
if (newInfo.availNum < 100) {
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++;
}
oldBlockInfo = newBlockInfo;
} catch (Exception e) {
Logger.log(new LogEvent(LogIDs.GUI, "drawing piece map", e));
} finally {
gcImg.dispose();
}
topLabelLHS = MessageText.getString("PiecesView.BlockView.Header", new String[] { "" + iNumCols, "" + (iRow + 1), "" + dm_pieces.length });
PiecePicker picker = pm.getPiecePicker();
int seq_info = picker.getSequentialInfo();
if (seq_info != 0) {
topLabelLHS += "; seq=" + seq_info;
}
String egm_info = picker.getEGMInfo();
if (egm_info != null) {
topLabelLHS += "; EGM=" + egm_info;
}
updateTopLabel();
pieceInfoCanvas.redraw();
}
Aggregations