Skip to content

Commit

Permalink
https://github.com/tonikelope/megabasterd/issues/643
Browse files Browse the repository at this point in the history
JOIN CHUNKS LOCK (one file at time)
  • Loading branch information
tonikelope committed Aug 6, 2024
1 parent 91dafbc commit 5353110
Showing 1 changed file with 58 additions and 37 deletions.
95 changes: 58 additions & 37 deletions src/main/java/com/tonikelope/megabasterd/ChunkWriterManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.CipherInputStream;
Expand All @@ -32,6 +33,8 @@ public class ChunkWriterManager implements Runnable, SecureSingleThreadNotifiabl

private static final Logger LOG = Logger.getLogger(ChunkWriterManager.class.getName());

private static final ReentrantLock JOIN_CHUNKS_LOCK = new ReentrantLock();

public static long calculateChunkOffset(long chunk_id, int size_multi) {
long[] offs = {0, 128, 384, 768, 1280, 1920, 2688};

Expand Down Expand Up @@ -179,71 +182,89 @@ public void run() {
LOG.log(Level.INFO, "{0} ChunkWriterManager LAST CHUNK WRITTEN -> [{1}] {2} {3}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.getFile_name()});
boolean download_finished = false;
if (_file_size > 0) {
while (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {

if (!download_finished && _download.getProgress() == _file_size) {
try {

finishDownload();
download_finished = true;
}
while (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {

boolean chunk_io_error;
if (!JOIN_CHUNKS_LOCK.isHeldByCurrentThread()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK LOCKED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
JOIN_CHUNKS_LOCK.lock();
}

do {
if (!download_finished && _download.getProgress() == _file_size) {

chunk_io_error = false;
finishDownload();
download_finished = true;
}

try {
boolean chunk_io_error;

File chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
do {

while (chunk_file.exists() && chunk_file.canRead() && chunk_file.canWrite() && chunk_file.length() > 0) {
chunk_io_error = false;

if (!download_finished && _download.getProgress() == _file_size) {
try {

finishDownload();
download_finished = true;
}
File chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));

byte[] buffer = new byte[MainPanel.DEFAULT_BYTE_BUFFER_SIZE];
while (chunk_file.exists() && chunk_file.canRead() && chunk_file.canWrite() && chunk_file.length() > 0) {

int reads;
if (!download_finished && _download.getProgress() == _file_size) {

try (CipherInputStream cis = new CipherInputStream(new BufferedInputStream(new FileInputStream(chunk_file)), genDecrypter("AES", "AES/CTR/NoPadding", _byte_file_key, forwardMEGALinkKeyIV(_byte_iv, _bytes_written)))) {
while ((reads = cis.read(buffer)) != -1) {
_download.getOutput_stream().write(buffer, 0, reads);
finishDownload();
download_finished = true;
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) {
LOG.log(Level.SEVERE, ex.getMessage());
}

_bytes_written += chunk_file.length();
byte[] buffer = new byte[MainPanel.DEFAULT_BYTE_BUFFER_SIZE];

_last_chunk_id_written++;
int reads;

try (CipherInputStream cis = new CipherInputStream(new BufferedInputStream(new FileInputStream(chunk_file)), genDecrypter("AES", "AES/CTR/NoPadding", _byte_file_key, forwardMEGALinkKeyIV(_byte_iv, _bytes_written)))) {
while ((reads = cis.read(buffer)) != -1) {
_download.getOutput_stream().write(buffer, 0, reads);
}
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException ex) {
LOG.log(Level.SEVERE, ex.getMessage());
}

LOG.log(Level.INFO, "{0} ChunkWriterManager has written to disk chunk [{1}] {2} {3} {4}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.calculateLastWrittenChunk(_bytes_written), _download.getFile_name()});
_bytes_written += chunk_file.length();

chunk_file.delete();
_last_chunk_id_written++;

chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
LOG.log(Level.INFO, "{0} ChunkWriterManager has written to disk chunk [{1}] {2} {3} {4}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written, _bytes_written, _download.calculateLastWrittenChunk(_bytes_written), _download.getFile_name()});

chunk_file.delete();

chunk_file = new File(getChunks_dir() + "/" + MiscTools.HashString("sha1", _download.getUrl()) + ".chunk" + String.valueOf(_last_chunk_id_written + 1));
}

} catch (IOException ex) {
chunk_io_error = true;
LOG.log(Level.WARNING, ex.getMessage());
MiscTools.pausar(1000);
}
} catch (IOException ex) {
chunk_io_error = true;
LOG.log(Level.WARNING, ex.getMessage());
MiscTools.pausar(1000);
}

} while (chunk_io_error);
} while (chunk_io_error);

if (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {
if (!_exit && (!_download.isStopped() || !_download.getChunkworkers().isEmpty()) && _bytes_written < _file_size) {

LOG.log(Level.INFO, "{0} ChunkWriterManager waiting for chunk [{1}] {2}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written + 1, _download.getFile_name()});
LOG.log(Level.INFO, "{0} ChunkWriterManager waiting for chunk [{1}] {2}...", new Object[]{Thread.currentThread().getName(), _last_chunk_id_written + 1, _download.getFile_name()});

secureWait();
if (JOIN_CHUNKS_LOCK.isHeldByCurrentThread() && JOIN_CHUNKS_LOCK.isLocked()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK RELEASED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
JOIN_CHUNKS_LOCK.unlock();
}

secureWait();
}
}

} finally {
if (JOIN_CHUNKS_LOCK.isHeldByCurrentThread() && JOIN_CHUNKS_LOCK.isLocked()) {
LOG.log(Level.INFO, "{0} ChunkWriterManager: JOIN LOCK RELEASED FOR {1}", new Object[]{Thread.currentThread().getName(), _download.getFile_name()});
JOIN_CHUNKS_LOCK.unlock();
}
}

if (_bytes_written == _file_size && MiscTools.isDirEmpty(Paths.get(getChunks_dir()))) {
Expand Down

0 comments on commit 5353110

Please sign in to comment.