Search in sources :

Example 6 with DiskManagerPiece

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;
    }
}
Also used : DiskManager(com.biglybt.pif.disk.DiskManager) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) DiskManagerFileInfoURL(com.biglybt.core.download.DiskManagerFileInfoURL) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) DiskManagerFileInfoURL(com.biglybt.core.download.DiskManagerFileInfoURL) URL(java.net.URL) DiskManagerPiece(com.biglybt.core.disk.DiskManagerPiece) Download(com.biglybt.pif.download.Download) IPCInterface(com.biglybt.pif.ipc.IPCInterface) DiskManagerFileInfo(com.biglybt.pif.disk.DiskManagerFileInfo) PluginInterface(com.biglybt.pif.PluginInterface) Average(com.biglybt.core.util.average.Average) URLConnection(java.net.URLConnection) TOTorrent(com.biglybt.core.torrent.TOTorrent)

Example 7 with DiskManagerPiece

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);
}
Also used : PooledByteBufferImpl(com.biglybt.pifimpl.local.utils.PooledByteBufferImpl) com.biglybt.pif.disk(com.biglybt.pif.disk) DiskManagerPiece(com.biglybt.core.disk.DiskManagerPiece) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer)

Example 8 with DiskManagerPiece

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);
        }
    }
}
Also used : PiecePicker(com.biglybt.core.peermanager.piecepicker.PiecePicker) DiskManager(com.biglybt.core.disk.DiskManager) DownloadManager(com.biglybt.core.download.DownloadManager) DiskManagerFileInfoListener(com.biglybt.core.disk.DiskManagerFileInfoListener) DownloadException(com.biglybt.pif.download.DownloadException) DiskManagerPiece(com.biglybt.core.disk.DiskManagerPiece) Download(com.biglybt.pif.download.Download) DownloadException(com.biglybt.pif.download.DownloadException) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) DownloadListener(com.biglybt.pif.download.DownloadListener) TOTorrent(com.biglybt.core.torrent.TOTorrent) PEPeerManager(com.biglybt.core.peer.PEPeerManager)

Example 9 with DiskManagerPiece

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();
}
Also used : PiecePicker(com.biglybt.core.peermanager.piecepicker.PiecePicker) Color(org.eclipse.swt.graphics.Color) Rectangle(org.eclipse.swt.graphics.Rectangle) Image(org.eclipse.swt.graphics.Image) PEPiece(com.biglybt.core.peer.PEPiece) DiskManagerPiece(com.biglybt.core.disk.DiskManagerPiece) GC(org.eclipse.swt.graphics.GC)

Example 10 with DiskManagerPiece

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);
}
Also used : DiskManagerFileInfo(com.biglybt.core.disk.DiskManagerFileInfo) DiskManagerPiece(com.biglybt.core.disk.DiskManagerPiece) DiskManager(com.biglybt.core.disk.DiskManager)

Aggregations

DiskManagerPiece (com.biglybt.core.disk.DiskManagerPiece)18 DiskManager (com.biglybt.core.disk.DiskManager)13 PEPeerManager (com.biglybt.core.peer.PEPeerManager)8 PEPiece (com.biglybt.core.peer.PEPiece)8 DownloadManager (com.biglybt.core.download.DownloadManager)6 DiskManagerFileInfo (com.biglybt.core.disk.DiskManagerFileInfo)5 LogEvent (com.biglybt.core.logging.LogEvent)5 PiecePicker (com.biglybt.core.peermanager.piecepicker.PiecePicker)5 DMPieceList (com.biglybt.core.disk.impl.piecemapper.DMPieceList)3 DMPieceMapEntry (com.biglybt.core.disk.impl.piecemapper.DMPieceMapEntry)3 GC (org.eclipse.swt.graphics.GC)3 Image (org.eclipse.swt.graphics.Image)3 Rectangle (org.eclipse.swt.graphics.Rectangle)3 PEPeer (com.biglybt.core.peer.PEPeer)2 TOTorrent (com.biglybt.core.torrent.TOTorrent)2 TOTorrentFile (com.biglybt.core.torrent.TOTorrentFile)2 AERunnable (com.biglybt.core.util.AERunnable)2 Download (com.biglybt.pif.download.Download)2 MenuBuildUtils (com.biglybt.ui.swt.MenuBuildUtils)2 UISWTViewEvent (com.biglybt.ui.swt.pif.UISWTViewEvent)2