use of com.biglybt.core.disk.DiskManagerPiece in project BiglyBT by BiglySoftware.
the class TranscodeQueueImpl method process.
protected boolean process(final TranscodeJobImpl job) {
TranscodePipe pipe = null;
current_job = job;
DeviceImpl device = job.getDevice();
device.setTranscoding(true);
try {
job.starts();
TranscodeProvider provider = job.getProfile().getProvider();
final TranscodeException[] error = { null };
TranscodeProfile profile = job.getProfile();
final TranscodeFileImpl transcode_file = job.getTranscodeFile();
TranscodeProviderAnalysis provider_analysis;
boolean xcode_required;
if (provider == null) {
xcode_required = false;
provider_analysis = null;
} else {
provider_analysis = analyse(job);
xcode_required = provider_analysis.getBooleanProperty(TranscodeProviderAnalysis.PT_TRANSCODE_REQUIRED);
int tt_req;
if (job.isStream()) {
// already advertised as a transcoded asset so no option not to
// transcode (as name/format would change if decided not to transcode and then
// this would confuse the clients)
tt_req = TranscodeTarget.TRANSCODE_ALWAYS;
} else {
tt_req = job.getTranscodeRequirement();
if (device instanceof TranscodeTarget) {
if (provider_analysis.getLongProperty(TranscodeProviderAnalysis.PT_VIDEO_HEIGHT) == 0) {
if (((TranscodeTarget) device).isAudioCompatible(transcode_file)) {
tt_req = TranscodeTarget.TRANSCODE_NEVER;
}
}
}
}
if (tt_req == TranscodeTarget.TRANSCODE_NEVER) {
xcode_required = false;
} else if (tt_req == TranscodeTarget.TRANSCODE_ALWAYS) {
xcode_required = true;
provider_analysis.setBooleanProperty(TranscodeProviderAnalysis.PT_FORCE_TRANSCODE, true);
}
}
if (xcode_required) {
final AESemaphore xcode_sem = new AESemaphore("xcode:proc");
final TranscodeProviderJob[] provider_job = { null };
TranscodeProviderAdapter xcode_adapter = new TranscodeProviderAdapter() {
private boolean resolution_updated;
private final int ETA_AVERAGE_SIZE = 10;
private int last_eta;
private int eta_samples;
private Average eta_average = AverageFactory.MovingAverage(ETA_AVERAGE_SIZE);
private int last_percent;
private long initial_file_downloaded = job.getFile().getDownloaded();
private long file_size = job.getFile().getLength();
@Override
public void updateProgress(int percent, int eta_secs, int new_width, int new_height) {
last_eta = eta_secs;
last_percent = percent;
TranscodeProviderJob prov_job = provider_job[0];
if (prov_job == null) {
return;
}
int job_state = job.getState();
if (job_state == TranscodeJob.ST_CANCELLED || job_state == TranscodeJob.ST_REMOVED) {
prov_job.cancel();
} else if (paused || job_state == TranscodeJob.ST_PAUSED) {
prov_job.pause();
} else {
if (job_state == TranscodeJob.ST_RUNNING) {
prov_job.resume();
}
job.updateProgress(percent, eta_secs);
prov_job.setMaxBytesPerSecond(max_bytes_per_sec);
if (!resolution_updated) {
if (new_width > 0 && new_height > 0) {
transcode_file.setResolution(new_width, new_height);
resolution_updated = true;
}
}
}
}
@Override
public void streamStats(long connect_rate, long write_speed) {
if (Constants.isOSX && job.getEnableAutoRetry() && job.canUseDirectInput() && job.getAutoRetryCount() == 0) {
if (connect_rate > 5 && last_percent < 100) {
long eta = (long) eta_average.update(last_eta);
eta_samples++;
if (eta_samples >= ETA_AVERAGE_SIZE) {
long total_time = (eta * 100) / (100 - last_percent);
long total_write = total_time * write_speed;
DiskManagerFileInfo file = job.getFile();
long length = file.getLength();
if (length > 0) {
double over_write = ((double) total_write) / length;
if (over_write > 5.0) {
failed(new TranscodeException("Overwrite limit exceeded, abandoning transcode"));
provider_job[0].cancel();
}
}
}
} else {
eta_samples = 0;
}
}
}
@Override
public void failed(TranscodeException e) {
try {
if (error[0] == null) {
error[0] = e;
}
if (e.isRetryDisabled()) {
job.setEnableAutoRetry(false);
}
} finally {
xcode_sem.release();
}
}
@Override
public void complete() {
try {
// sanity check: for incomplete files at the start of the process ensure that they have completed
long current_downloaded = job.getFile().getDownloaded();
if (file_size > 0 && initial_file_downloaded < file_size && current_downloaded < file_size) {
if (error[0] == null) {
// actually this ain't so simple as we stream data prior to hash check completion (otherwise for
// large piece sizes we could be waiting for 4MB to complete downloading before playback)
// and getDownloaded() only returns the verified data size
long contiguous_downloaded = 0;
try {
DiskManagerFileInfo _file_info = job.getFile();
Download download = _file_info.getDownload();
com.biglybt.core.disk.DiskManagerFileInfo file_info = PluginCoreUtils.unwrap(_file_info);
TOTorrentFile torrent_file = file_info.getTorrentFile();
TOTorrent torrent = torrent_file.getTorrent();
TOTorrentFile[] torrent_files = torrent.getFiles();
long byte_start = 0;
for (TOTorrentFile tf : torrent_files) {
if (tf == torrent_file) {
break;
}
byte_start += tf.getLength();
}
DiskManager dm = download.getDiskManager();
if (dm == null) {
throw (new Exception("Download stopped"));
}
DiskManagerPiece[] pieces = PluginCoreUtils.unwrap(dm).getPieces();
long piece_size = torrent.getPieceLength();
int first_piece_index = (int) (byte_start / piece_size);
int first_piece_offset = (int) (byte_start % piece_size);
int last_piece_index = torrent_file.getLastPieceNumber();
DiskManagerPiece first_piece = pieces[first_piece_index];
if (!first_piece.isDone()) {
boolean[] blocks = first_piece.getWritten();
if (blocks == null) {
if (first_piece.isDone()) {
contiguous_downloaded = first_piece.getLength() - first_piece_offset;
}
} else {
int piece_offset = 0;
for (int j = 0; j < blocks.length; j++) {
if (blocks[j]) {
int block_size = first_piece.getBlockSize(j);
piece_offset = piece_offset + block_size;
if (contiguous_downloaded == 0) {
if (piece_offset > first_piece_offset) {
contiguous_downloaded = piece_offset - first_piece_offset;
}
} else {
contiguous_downloaded += block_size;
}
} else {
break;
}
}
}
} else {
contiguous_downloaded = first_piece.getLength() - first_piece_offset;
for (int i = first_piece_index + 1; i <= last_piece_index; i++) {
DiskManagerPiece piece = pieces[i];
if (piece.isDone()) {
contiguous_downloaded += piece.getLength();
} else {
boolean[] blocks = piece.getWritten();
if (blocks == null) {
if (piece.isDone()) {
contiguous_downloaded += piece.getLength();
} else {
break;
}
} else {
for (int j = 0; j < blocks.length; j++) {
if (blocks[j]) {
contiguous_downloaded += piece.getBlockSize(j);
} else {
break;
}
}
}
break;
}
}
}
} catch (Throwable e) {
// Debug.out( e );
}
if (contiguous_downloaded < file_size) {
// things might have improved, check again
current_downloaded = job.getFile().getDownloaded();
if (current_downloaded < file_size) {
Debug.out("Premature transcode termination: init=" + initial_file_downloaded + ", curr=" + current_downloaded + ", len=" + file_size);
error[0] = new TranscodeException("Transcode terminated prematurely");
}
}
}
}
} finally {
xcode_sem.release();
}
}
};
boolean direct_input = job.useDirectInput();
if (job.isStream()) {
/*
provider_job[0] =
provider.transcode(
adapter,
job.getFile(),
profile,
new File( "C:\\temp\\arse").toURI().toURL());
*/
pipe = new TranscodePipeStreamSource2(new TranscodePipeStreamSource2.streamListener() {
@Override
public void gotStream(InputStream is) {
job.setStream(is);
}
});
provider_job[0] = provider.transcode(xcode_adapter, provider_analysis, direct_input, job.getFile(), profile, new URL("tcp://127.0.0.1:" + pipe.getPort()));
} else {
File output_file = transcode_file.getCacheFile();
provider_job[0] = provider.transcode(xcode_adapter, provider_analysis, direct_input, job.getFile(), profile, output_file.toURI().toURL());
}
provider_job[0].setMaxBytesPerSecond(max_bytes_per_sec);
TranscodeQueueListener listener = new TranscodeQueueListener() {
@Override
public void jobAdded(TranscodeJob job) {
}
@Override
public void jobChanged(TranscodeJob changed_job) {
if (changed_job == job) {
int state = job.getState();
if (state == TranscodeJob.ST_PAUSED) {
provider_job[0].pause();
} else if (state == TranscodeJob.ST_RUNNING) {
provider_job[0].resume();
} else if (state == TranscodeJob.ST_CANCELLED || state == TranscodeJob.ST_STOPPED) {
provider_job[0].cancel();
}
}
}
@Override
public void jobRemoved(TranscodeJob removed_job) {
if (removed_job == job) {
provider_job[0].cancel();
}
}
};
try {
addListener(listener);
xcode_sem.reserve();
} finally {
removeListener(listener);
}
if (error[0] != null) {
throw (error[0]);
}
} else {
// no transcode required...
DiskManagerFileInfo source = job.getFile();
transcode_file.setTranscodeRequired(false);
if (job.isStream()) {
PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID("azupnpav");
if (av_pi == null) {
throw (new TranscodeException("Media Server plugin not found"));
}
IPCInterface av_ipc = av_pi.getIPC();
String url_str = (String) av_ipc.invoke("getContentURL", new Object[] { source });
if (url_str == null || url_str.length() == 0) {
// see if we can use the file directly
File source_file = source.getFile();
if (source_file.exists()) {
job.setStream(new BufferedInputStream(new FileInputStream(source_file)));
} else {
throw (new TranscodeException("No UPnPAV URL and file doesn't exist"));
}
} else {
URL source_url = new URL(url_str);
job.setStream(source_url.openConnection().getInputStream());
}
} else {
boolean url_input_source = source instanceof DiskManagerFileInfoURL;
if (device.getAlwaysCacheFiles() || url_input_source) {
PluginInterface av_pi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByID("azupnpav");
if (av_pi == null) {
throw (new TranscodeException("Media Server plugin not found"));
}
IPCInterface av_ipc = av_pi.getIPC();
String url_str = (String) av_ipc.invoke("getContentURL", new Object[] { source });
InputStream is;
long length;
if (url_str == null || url_str.length() == 0) {
if (url_input_source) {
((DiskManagerFileInfoURL) source).download();
}
File source_file = source.getFile();
if (source_file.exists()) {
is = new BufferedInputStream(new FileInputStream(source_file));
length = source_file.length();
} else {
throw (new TranscodeException("No UPnPAV URL and file doesn't exist"));
}
} else {
URL source_url = new URL(url_str);
URLConnection connection = source_url.openConnection();
is = source_url.openConnection().getInputStream();
String s = connection.getHeaderField("content-length");
if (s != null) {
length = Long.parseLong(s);
} else {
length = -1;
}
}
OutputStream os = null;
final boolean[] cancel_copy = { false };
TranscodeQueueListener copy_listener = new TranscodeQueueListener() {
@Override
public void jobAdded(TranscodeJob job) {
}
@Override
public void jobChanged(TranscodeJob changed_job) {
if (changed_job == job) {
int state = job.getState();
if (state == TranscodeJob.ST_PAUSED) {
} else if (state == TranscodeJob.ST_RUNNING) {
} else if (state == TranscodeJob.ST_CANCELLED || state == TranscodeJob.ST_STOPPED) {
cancel_copy[0] = true;
}
}
}
@Override
public void jobRemoved(TranscodeJob removed_job) {
if (removed_job == job) {
cancel_copy[0] = true;
}
}
};
try {
addListener(copy_listener);
os = new FileOutputStream(transcode_file.getCacheFile());
long total_copied = 0;
byte[] buffer = new byte[128 * 1024];
while (true) {
if (cancel_copy[0]) {
throw (new TranscodeException("Copy cancelled"));
}
int len = is.read(buffer);
if (len <= 0) {
break;
}
os.write(buffer, 0, len);
total_copied += len;
if (length > 0) {
job.updateProgress((int) (total_copied * 100 / length), -1);
}
total_copied += len;
}
} finally {
try {
is.close();
} catch (Throwable e) {
Debug.out(e);
}
try {
if (os != null) {
os.close();
}
} catch (Throwable e) {
Debug.out(e);
}
removeListener(copy_listener);
}
}
}
}
job.complete();
return (true);
} catch (Throwable e) {
job.failed(e);
e.printStackTrace();
if (!job.isStream() && job.getEnableAutoRetry() && job.getAutoRetryCount() == 0 && job.canUseDirectInput() && !job.useDirectInput()) {
log("Auto-retrying transcode with direct input");
job.setUseDirectInput();
job.setAutoRetry(true);
queue_sem.release();
}
return (false);
} finally {
if (pipe != null) {
pipe.destroy();
}
device.setTranscoding(false);
current_job = null;
}
}
use of com.biglybt.core.disk.DiskManagerPiece in project BiglyBT by BiglySoftware.
the class DiskManagerImpl method write.
@Override
public DiskManagerWriteRequest write(final int piece_number, final int offset, PooledByteBuffer data, final DiskManagerWriteRequestListener listener) throws DiskManagerException {
DirectByteBuffer buffer = ((PooledByteBufferImpl) data).getBuffer();
if (!disk_manager.checkBlockConsistencyForWrite("plugin", piece_number, offset, buffer)) {
throw (new DiskManagerException("write invalid - parameters incorrect"));
}
final int length = buffer.remaining(DirectByteBuffer.SS_EXTERNAL);
final DMWR request = new DMWR(disk_manager.createWriteRequest(piece_number, offset, buffer, null), length);
disk_manager.enqueueWriteRequest(request.getDelegate(), new com.biglybt.core.disk.DiskManagerWriteRequestListener() {
@Override
public void writeCompleted(com.biglybt.core.disk.DiskManagerWriteRequest _request) {
DiskManagerPiece[] dm_pieces = disk_manager.getPieces();
DiskManagerPiece dm_piece = dm_pieces[piece_number];
if (!dm_piece.isDone()) {
int current_offset = offset;
for (int i = 0; i < length; i += DiskManager.BLOCK_SIZE) {
dm_piece.setWritten(current_offset / DiskManager.BLOCK_SIZE);
current_offset += DiskManager.BLOCK_SIZE;
}
}
listener.complete(request);
}
@Override
public void writeFailed(com.biglybt.core.disk.DiskManagerWriteRequest _request, Throwable _cause) {
listener.failed(request, new DiskManagerException("read failed", _cause));
}
});
return (request);
}
use of com.biglybt.core.disk.DiskManagerPiece in project BiglyBT by BiglySoftware.
the class DiskManagerRandomReadController method executeRequest.
private void executeRequest() {
DiskManagerRandomReadRequestImpl request;
synchronized (requests) {
if (requests.isEmpty()) {
return;
}
request = requests.remove(0);
}
if (request.isCancelled()) {
return;
}
DiskManagerFileInfoListener info_listener = null;
com.biglybt.core.disk.DiskManagerFileInfo core_file = request.getFile().getCore();
DownloadManager core_download = core_file.getDownloadManager();
int prev_hint_piece = -1;
int curr_hint_piece = -1;
try {
if (core_download.getTorrent() == null) {
throw (new DownloadException("Torrent invalid"));
}
if (core_download.isDestroyed()) {
Debug.out("Download has been removed");
throw (new DownloadException("Download has been removed"));
}
TOTorrentFile tf = core_file.getTorrentFile();
TOTorrent torrent = tf.getTorrent();
TOTorrentFile[] tfs = torrent.getFiles();
long core_file_start_byte = 0;
for (int i = 0; i < core_file.getIndex(); i++) {
core_file_start_byte += tfs[i].getLength();
}
long download_byte_start = core_file_start_byte + request.getOffset();
long download_byte_end = download_byte_start + request.getLength();
int piece_size = (int) tf.getTorrent().getPieceLength();
if (core_file.getDownloaded() != core_file.getLength()) {
if (core_file.isSkipped()) {
core_file.setSkipped(false);
}
boolean force_start = download.isForceStart();
if (!force_start) {
download.setForceStart(true);
set_force_start = true;
final AESemaphore running_sem = new AESemaphore("rs");
DownloadListener dl_listener = new DownloadListener() {
@Override
public void stateChanged(Download download, int old_state, int new_state) {
if (new_state == Download.ST_DOWNLOADING || new_state == Download.ST_SEEDING) {
running_sem.release();
}
}
@Override
public void positionChanged(Download download, int oldPosition, int newPosition) {
}
};
download.addListener(dl_listener);
try {
if (download.getState() != Download.ST_DOWNLOADING && download.getState() != Download.ST_SEEDING) {
if (!running_sem.reserve(10 * 1000)) {
throw (new DownloadException("timeout waiting for download to start"));
}
}
} finally {
download.removeListener(dl_listener);
}
}
}
boolean is_reverse = request.isReverse();
final AESemaphore wait_sem = new AESemaphore("rr:waiter");
info_listener = new DiskManagerFileInfoListener() {
@Override
public void dataWritten(long offset, long length) {
wait_sem.release();
}
@Override
public void dataChecked(long offset, long length) {
}
};
long start_time = SystemTime.getMonotonousTime();
boolean has_started = false;
core_file.addListener(info_listener);
while (download_byte_start < download_byte_end) {
if (request.isCancelled()) {
throw (new Exception("request cancelled"));
}
// System.out.println( "Request current: " + download_byte_start + " -> " + download_byte_end );
long now = SystemTime.getMonotonousTime();
int piece_start = (int) (download_byte_start / piece_size);
int piece_start_offset = (int) (download_byte_start % piece_size);
int piece_end = (int) ((download_byte_end - 1) / piece_size);
int piece_end_offset = (int) ((download_byte_end - 1) % piece_size) + 1;
// System.out.println( " piece details: " + piece_start + "/" + piece_start_offset + " -> " + piece_end + "/" + piece_end_offset );
DiskManagerPiece[] pieces = null;
DiskManager disk_manager = core_download.getDiskManager();
if (disk_manager != null) {
pieces = disk_manager.getPieces();
}
long avail_start;
long avail_end;
if (pieces == null) {
if (core_file.getDownloaded() == core_file.getLength()) {
avail_start = download_byte_start;
avail_end = download_byte_end;
} else {
if (now - start_time < 10000 && !has_started) {
wait_sem.reserve(250);
continue;
}
throw (new Exception("download stopped"));
}
} else {
has_started = true;
if (is_reverse) {
long min_done = download_byte_end;
for (int i = piece_end; i >= piece_start; i--) {
int p_start = i == piece_start ? piece_start_offset : 0;
int p_end = i == piece_end ? piece_end_offset : piece_size;
DiskManagerPiece piece = pieces[i];
boolean[] done = piece.getWritten();
if (done == null) {
if (piece.isDone()) {
min_done = i * (long) piece_size;
continue;
} else {
break;
}
}
int block_size = piece.getBlockSize(0);
int first_block = p_start / block_size;
int last_block = (p_end - 1) / block_size;
for (int j = last_block; j >= first_block; j--) {
if (done[j]) {
min_done = i * (long) piece_size + j * block_size;
} else {
break;
}
}
}
avail_start = Math.max(download_byte_start, min_done);
avail_end = download_byte_end;
} else {
long max_done = download_byte_start;
for (int i = piece_start; i <= piece_end; i++) {
int p_start = i == piece_start ? piece_start_offset : 0;
int p_end = i == piece_end ? piece_end_offset : piece_size;
DiskManagerPiece piece = pieces[i];
boolean[] done = piece.getWritten();
if (done == null) {
if (piece.isDone()) {
max_done = (i + 1) * (long) piece_size;
continue;
} else {
break;
}
}
int block_size = piece.getBlockSize(0);
int first_block = p_start / block_size;
int last_block = (p_end - 1) / block_size;
for (int j = first_block; j <= last_block; j++) {
if (done[j]) {
max_done = i * (long) piece_size + (j + 1) * block_size;
} else {
break;
}
}
}
avail_start = download_byte_start;
avail_end = Math.min(download_byte_end, max_done);
}
}
// System.out.println( " avail: " + avail_start + " -> " + avail_end );
int max_chunk = 128 * 1024;
if (avail_end > avail_start) {
long length = avail_end - avail_start;
if (length > max_chunk) {
if (is_reverse) {
avail_start = avail_end - max_chunk;
} else {
avail_end = avail_start + max_chunk;
}
}
// System.out.println( "got data: " + avail_start + " -> " + avail_end );
long read_offset = avail_start - core_file_start_byte;
int read_length = (int) (avail_end - avail_start);
DirectByteBuffer buffer = core_file.read(read_offset, read_length);
request.dataAvailable(buffer, read_offset, read_length);
if (is_reverse) {
download_byte_end = avail_start;
} else {
download_byte_start = avail_end;
}
continue;
}
PEPeerManager pm = core_download.getPeerManager();
if (pm == null) {
if (now - start_time < 10000 && !has_started) {
wait_sem.reserve(250);
continue;
}
throw (new Exception("download stopped"));
} else {
has_started = true;
}
PiecePicker picker = pm.getPiecePicker();
picker.setReverseBlockOrder(is_reverse);
int hint_piece;
int hint_offset;
int hint_length;
if (piece_start == piece_end) {
hint_piece = piece_start;
hint_offset = piece_start_offset;
hint_length = piece_end_offset - piece_start_offset;
} else {
if (is_reverse) {
hint_piece = piece_end;
hint_offset = 0;
hint_length = piece_end_offset;
} else {
hint_piece = piece_start;
hint_offset = piece_start_offset;
hint_length = piece_size - piece_start_offset;
}
}
if (curr_hint_piece == -1) {
int[] existing = picker.getGlobalRequestHint();
if (existing != null) {
curr_hint_piece = existing[0];
}
}
// System.out.println( "hint: " + hint_piece + "/" + hint_offset + "/" + hint_length + ": curr=" + curr_hint_piece + ", prev=" + prev_hint_piece );
picker.setGlobalRequestHint(hint_piece, hint_offset, hint_length);
if (hint_piece != curr_hint_piece) {
prev_hint_piece = curr_hint_piece;
curr_hint_piece = hint_piece;
}
if (prev_hint_piece != -1) {
clearHint(pm, prev_hint_piece);
}
wait_sem.reserve(250);
}
} catch (Throwable e) {
request.failed(e);
} finally {
PEPeerManager pm = core_download.getPeerManager();
if (pm != null) {
PiecePicker picker = pm.getPiecePicker();
if (picker != null) {
picker.setReverseBlockOrder(false);
picker.setGlobalRequestHint(-1, 0, 0);
if (curr_hint_piece != -1) {
clearHint(pm, curr_hint_piece);
}
}
}
if (info_listener != null) {
core_file.removeListener(info_listener);
}
}
}
use of com.biglybt.core.disk.DiskManagerPiece in project BiglyBT by BiglySoftware.
the class PieceDistributionView method updateDistribution.
private final void updateDistribution() {
if (!initialized || pem == null || comp == null || pem.getPiecePicker() == null || pem.getDiskManager() == null || !comp.isVisible())
return;
Rectangle rect = pieceDistCanvas.getBounds();
if (rect.height <= 0 || rect.width <= 0)
return;
PiecePicker picker = pem.getPiecePicker();
final int seeds = pem.getNbSeeds() + (pem.isSeeding() ? 1 : 0);
final int connected = pem.getNbPeers() + seeds + (pem.isSeeding() ? 0 : 1);
final int upperBound = 1 + (1 << (int) Math.ceil(Math.log(connected + 0.0) / Math.log(2.0)));
// System.out.println("conn:"+connected+" bound:"+upperBound);
final int minAvail = (int) picker.getMinAvailability();
// final int maxAvail = picker.getMaxAvailability();
final int nbPieces = picker.getNumberOfPieces();
final int[] availabilties = picker.getAvailability();
final DiskManagerPiece[] dmPieces = pem.getDiskManager().getPieces();
final PEPiece[] pePieces = pem.getPieces();
final int[] globalPiecesPerAvailability = new int[upperBound];
final int[] datasourcePiecesPerAvailability = new int[upperBound];
// me-only stuff
final boolean[] downloading = new boolean[upperBound];
int avlPeak = 0;
for (int i = 0; i < nbPieces; i++) {
if (availabilties[i] >= upperBound)
// availability and peer lists are OOS, just wait for the next round
return;
final int newPeak;
if (avlPeak < (newPeak = ++globalPiecesPerAvailability[availabilties[i]])) {
avlPeak = newPeak;
// avlPeakIdx = availabilties[i];
}
if ((isMe && dmPieces[i].isDone()) || (!isMe && hasPieces != null && hasPieces[i]))
++datasourcePiecesPerAvailability[availabilties[i]];
if (isMe && pePieces[i] != null)
downloading[availabilties[i]] = true;
}
Image img = new Image(comp.getDisplay(), pieceDistCanvas.getBounds());
GC gc = new GC(img);
try {
int stepWidthX = rect.width / upperBound;
int barGap = 1;
int barWidth = stepWidthX - barGap - 1;
int barFillingWidth = barWidth - 1;
double stepWidthY = 1.0 * (rect.height - 1) / avlPeak;
int offsetY = rect.height;
gc.setForeground(Colors.green);
for (int i = 0; i <= connected; i++) {
Color curColor;
if (i == 0)
curColor = Colors.colorError;
else if (i <= seeds)
curColor = Colors.green;
else
curColor = Colors.blues[Colors.BLUES_DARKEST];
gc.setBackground(curColor);
gc.setForeground(curColor);
if (globalPiecesPerAvailability[i] == 0) {
gc.setLineWidth(2);
gc.drawLine(stepWidthX * i, offsetY - 1, stepWidthX * (i + 1) - barGap, offsetY - 1);
} else {
gc.setLineWidth(1);
if (downloading[i])
gc.setLineStyle(SWT.LINE_DASH);
gc.fillRectangle(stepWidthX * i + 1, offsetY - 1, barFillingWidth, (int) (Math.ceil(stepWidthY * datasourcePiecesPerAvailability[i] - 1) * -1));
gc.drawRectangle(stepWidthX * i, offsetY, barWidth, (int) (Math.ceil(stepWidthY * globalPiecesPerAvailability[i]) + 1) * -1);
}
if (i == minAvail) {
gc.setForeground(Colors.blue);
gc.drawRectangle(stepWidthX * i + 1, offsetY - 1, barWidth - 2, (int) (Math.ceil(stepWidthY * globalPiecesPerAvailability[i] - 1)) * -1);
}
gc.setLineStyle(SWT.LINE_SOLID);
}
gc.setLineWidth(1);
String[] boxContent = new String[] { MessageText.getString("PiecesView.DistributionView.NoAvl"), MessageText.getString("PiecesView.DistributionView.SeedAvl"), MessageText.getString("PiecesView.DistributionView.PeerAvl"), MessageText.getString("PiecesView.DistributionView.RarestAvl", new String[] { globalPiecesPerAvailability[minAvail] + "", minAvail + "" }), MessageText.getString("PiecesView.DistributionView." + (isMe ? "weHave" : "theyHave")), MessageText.getString("PiecesView.DistributionView.weDownload") };
int charWidth = gc.getFontMetrics().getAverageCharWidth();
int charHeight = gc.getFontMetrics().getHeight();
int maxBoxOffsetY = charHeight + 2;
int maxBoxWidth = 0;
int maxBoxOffsetX = 0;
for (int i = 0; i < boxContent.length; i++) maxBoxWidth = Math.max(maxBoxWidth, boxContent[i].length());
maxBoxOffsetX = (maxBoxWidth + 5) * charWidth;
maxBoxWidth = ++maxBoxWidth * charWidth;
int boxNum = 1;
gc.setForeground(Colors.colorError);
gc.setBackground(Colors.background);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
boxNum++;
gc.setForeground(Colors.green);
gc.setBackground(Colors.background);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
boxNum++;
gc.setForeground(Colors.blues[Colors.BLUES_DARKEST]);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
boxNum++;
gc.setForeground(Colors.blue);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
boxNum++;
gc.setForeground(Colors.black);
gc.setBackground(Colors.black);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.fillRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth / 2, charHeight);
gc.setForeground(Colors.grey);
gc.setBackground(Colors.background);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
if (isMe) {
boxNum++;
gc.setForeground(Colors.black);
gc.setLineStyle(SWT.LINE_DASH);
gc.drawRectangle(rect.width + (maxBoxOffsetX) * -1, maxBoxOffsetY * boxNum, maxBoxWidth, charHeight);
gc.drawString(boxContent[boxNum - 1], rect.width + (maxBoxOffsetX - 5) * -1, maxBoxOffsetY * boxNum, true);
}
gc.setLineStyle(SWT.LINE_SOLID);
} finally {
gc.dispose();
}
if (imgToPaint != null) {
imgToPaint.dispose();
}
imgToPaint = img;
pieceDistCanvas.redraw();
}
use of com.biglybt.core.disk.DiskManagerPiece in project BiglyBT by BiglySoftware.
the class EnhancedDownloadManager method getContiguousAvailableBytes.
public long getContiguousAvailableBytes(int file_index, long file_start_offset, long stop_counting_after) {
if (file_index < 0 || file_index >= enhanced_files.length) {
return (-1);
}
EnhancedDownloadManagerFile efile = enhanced_files[file_index];
DiskManagerFileInfo file = efile.getFile();
DiskManager dm = download_manager.getDiskManager();
if (dm == null) {
if (file.getDownloaded() == file.getLength()) {
return (file.getLength() - file_start_offset);
}
return (-1);
}
int piece_size = dm.getPieceLength();
long start_index = efile.getByteOffestInTorrent() + file_start_offset;
int first_piece_index = (int) (start_index / piece_size);
int first_piece_offset = (int) (start_index % piece_size);
int last_piece_index = file.getLastPieceNumber();
DiskManagerPiece[] pieces = dm.getPieces();
DiskManagerPiece first_piece = pieces[first_piece_index];
long available = 0;
if (!first_piece.isDone()) {
boolean[] blocks = first_piece.getWritten();
if (blocks == null) {
if (first_piece.isDone()) {
available = first_piece.getLength() - first_piece_offset;
}
} else {
int piece_offset = 0;
for (int j = 0; j < blocks.length; j++) {
if (blocks[j]) {
int block_size = first_piece.getBlockSize(j);
piece_offset = piece_offset + block_size;
if (available == 0) {
if (piece_offset > first_piece_offset) {
available = piece_offset - first_piece_offset;
}
} else {
available += block_size;
}
} else {
break;
}
}
}
} else {
available = first_piece.getLength() - first_piece_offset;
for (int i = first_piece_index + 1; i <= last_piece_index; i++) {
if (stop_counting_after > 0 && available >= stop_counting_after) {
break;
}
DiskManagerPiece piece = pieces[i];
if (piece.isDone()) {
available += piece.getLength();
} else {
boolean[] blocks = piece.getWritten();
if (blocks == null) {
if (piece.isDone()) {
available += piece.getLength();
} else {
break;
}
} else {
for (int j = 0; j < blocks.length; j++) {
if (blocks[j]) {
available += piece.getBlockSize(j);
} else {
break;
}
}
}
break;
}
}
}
long max_available = file.getLength() - file_start_offset;
if (available > max_available) {
available = max_available;
}
return (available);
}
Aggregations