Skip to content

Commit

Permalink
Add option to align file to piece boundary when creating new torrent
Browse files Browse the repository at this point in the history
Alignment is achieved by adding dummy pad files between files which is
handled by libtorrent.
Closes #10460.
  • Loading branch information
Chocobo1 committed Sep 14, 2019
1 parent b144d3b commit edcc74c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 21 deletions.
12 changes: 6 additions & 6 deletions src/base/bittorrent/torrentcreatorthread.cpp
Expand Up @@ -54,7 +54,7 @@ namespace
#else
using LTCreateFlags = lt::create_flags_t;
using LTPieceIndex = lt::piece_index_t;
#endif
#endif

// do not include files and folders whose
// name starts with a .
Expand Down Expand Up @@ -138,8 +138,8 @@ void TorrentCreatorThread::run()

if (isInterruptionRequested()) return;

lt::create_torrent newTorrent(fs, m_params.pieceSize, -1
, (m_params.isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {}));
lt::create_torrent newTorrent(fs, m_params.pieceSize, m_params.paddedFileSizeLimit
, (m_params.isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {}));

// Add url seeds
for (QString seed : asConst(m_params.urlSeeds)) {
Expand Down Expand Up @@ -205,14 +205,14 @@ void TorrentCreatorThread::run()
}
}

int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized)
int TorrentCreatorThread::calculateTotalPieces(const QString &inputPath, const int pieceSize, const bool isAlignmentOptimized, const int paddedFileSizeLimit)
{
if (inputPath.isEmpty())
return 0;

lt::file_storage fs;
lt::add_files(fs, Utils::Fs::toNativePath(inputPath).toStdString(), fileFilter);

return lt::create_torrent(fs, pieceSize, -1
, (isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {})).num_pieces();
return lt::create_torrent(fs, pieceSize, paddedFileSizeLimit
, (isAlignmentOptimized ? lt::create_torrent::optimize_alignment : LTCreateFlags {})).num_pieces();
}
4 changes: 3 additions & 1 deletion src/base/bittorrent/torrentcreatorthread.h
Expand Up @@ -39,6 +39,7 @@ namespace BitTorrent
bool isPrivate;
bool isAlignmentOptimized;
int pieceSize;
int paddedFileSizeLimit;
QString inputPath;
QString savePath;
QString comment;
Expand All @@ -57,7 +58,8 @@ namespace BitTorrent

void create(const TorrentCreatorParams &params);

static int calculateTotalPieces(const QString &inputPath, int pieceSize, bool isAlignmentOptimized);
static int calculateTotalPieces(const QString &inputPath
, const int pieceSize, const bool isAlignmentOptimized, int paddedFileSizeLimit);

protected:
void run() override;
Expand Down
36 changes: 27 additions & 9 deletions src/gui/torrentcreatordialog.cpp
Expand Up @@ -55,6 +55,7 @@ TorrentCreatorDialog::TorrentCreatorDialog(QWidget *parent, const QString &defau
, m_storeStartSeeding(SETTINGS_KEY("StartSeeding"))
, m_storeIgnoreRatio(SETTINGS_KEY("IgnoreRatio"))
, m_storeOptimizeAlignment(SETTINGS_KEY("OptimizeAlignment"), true)
, m_paddedFileSizeLimit(SETTINGS_KEY("PaddedFileSizeLimit"), -1)
, m_storeLastAddPath(SETTINGS_KEY("LastAddPath"), QDir::homePath())
, m_storeTrackerList(SETTINGS_KEY("TrackerList"))
, m_storeWebSeedList(SETTINGS_KEY("WebSeedList"))
Expand Down Expand Up @@ -117,6 +118,12 @@ int TorrentCreatorDialog::getPieceSize() const
return pieceSizes[m_ui->comboPieceSize->currentIndex()] * 1024;
}

int TorrentCreatorDialog::getPaddedFileSizeLimit() const
{
const int value = m_ui->spinPaddedFileSizeLimit->value();
return ((value >= 0) ? (value * 1024) : -1);
}

void TorrentCreatorDialog::dropEvent(QDropEvent *event)
{
event->acceptProposedAction();
Expand Down Expand Up @@ -164,14 +171,19 @@ void TorrentCreatorDialog::onCreateButtonClicked()

const QStringList trackers = m_ui->trackersList->toPlainText().trimmed()
.replace(QRegularExpression("\n\n[\n]+"), "\n\n").split('\n');
const QStringList urlSeeds = m_ui->URLSeedsList->toPlainText().split('\n', QString::SkipEmptyParts);
const QString comment = m_ui->txtComment->toPlainText();
const QString source = m_ui->lineEditSource->text();
const BitTorrent::TorrentCreatorParams params {
m_ui->checkPrivate->isChecked()
, m_ui->checkOptimizeAlignment->isChecked()
, getPieceSize(), getPaddedFileSizeLimit()
, input, destination
, m_ui->txtComment->toPlainText()
, m_ui->lineEditSource->text()
, trackers
, m_ui->URLSeedsList->toPlainText().split('\n', QString::SkipEmptyParts)
};

// run the creator thread
m_creatorThread->create({ m_ui->checkPrivate->isChecked()
, m_ui->checkOptimizeAlignment->isChecked(), getPieceSize()
, input, destination, comment, source, trackers, urlSeeds });
m_creatorThread->create(params);
}

void TorrentCreatorDialog::handleCreationFailure(const QString &msg)
Expand Down Expand Up @@ -216,11 +228,12 @@ void TorrentCreatorDialog::updatePiecesCount()
const QString path = m_ui->textInputPath->text().trimmed();
const bool isAlignmentOptimized = m_ui->checkOptimizeAlignment->isChecked();

const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path, getPieceSize(), isAlignmentOptimized);
const int count = BitTorrent::TorrentCreatorThread::calculateTotalPieces(path
, getPieceSize(), isAlignmentOptimized, getPaddedFileSizeLimit());
m_ui->labelTotalPieces->setText(QString::number(count));
}

void TorrentCreatorDialog::setInteractionEnabled(bool enabled)
void TorrentCreatorDialog::setInteractionEnabled(const bool enabled) const
{
m_ui->textInputPath->setEnabled(enabled);
m_ui->addFileButton->setEnabled(enabled);
Expand All @@ -229,10 +242,13 @@ void TorrentCreatorDialog::setInteractionEnabled(bool enabled)
m_ui->URLSeedsList->setEnabled(enabled);
m_ui->txtComment->setEnabled(enabled);
m_ui->comboPieceSize->setEnabled(enabled);
m_ui->buttonCalcTotalPieces->setEnabled(enabled);
m_ui->checkPrivate->setEnabled(enabled);
m_ui->checkStartSeeding->setEnabled(enabled);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enabled);
m_ui->checkIgnoreShareLimits->setEnabled(enabled && m_ui->checkStartSeeding->isChecked());
m_ui->checkOptimizeAlignment->setEnabled(enabled);
m_ui->spinPaddedFileSizeLimit->setEnabled(enabled);
}

void TorrentCreatorDialog::saveSettings()
Expand All @@ -244,6 +260,7 @@ void TorrentCreatorDialog::saveSettings()
m_storeStartSeeding = m_ui->checkStartSeeding->isChecked();
m_storeIgnoreRatio = m_ui->checkIgnoreShareLimits->isChecked();
m_storeOptimizeAlignment = m_ui->checkOptimizeAlignment->isChecked();
m_paddedFileSizeLimit = m_ui->spinPaddedFileSizeLimit->value();

m_storeTrackerList = m_ui->trackersList->toPlainText();
m_storeWebSeedList = m_ui->URLSeedsList->toPlainText();
Expand All @@ -261,8 +278,9 @@ void TorrentCreatorDialog::loadSettings()
m_ui->checkPrivate->setChecked(m_storePrivateTorrent);
m_ui->checkStartSeeding->setChecked(m_storeStartSeeding);
m_ui->checkIgnoreShareLimits->setChecked(m_storeIgnoreRatio);
m_ui->checkOptimizeAlignment->setChecked(m_storeOptimizeAlignment);
m_ui->checkIgnoreShareLimits->setEnabled(m_ui->checkStartSeeding->isChecked());
m_ui->checkOptimizeAlignment->setChecked(m_storeOptimizeAlignment);
m_ui->spinPaddedFileSizeLimit->setValue(m_paddedFileSizeLimit);

m_ui->trackersList->setPlainText(m_storeTrackerList);
m_ui->URLSeedsList->setPlainText(m_storeWebSeedList);
Expand Down
5 changes: 4 additions & 1 deletion src/gui/torrentcreatordialog.h
Expand Up @@ -68,8 +68,10 @@ private slots:

void saveSettings();
void loadSettings();
void setInteractionEnabled(bool enabled) const;

int getPieceSize() const;
void setInteractionEnabled(bool enabled);
int getPaddedFileSizeLimit() const;

Ui::TorrentCreatorDialog *m_ui;
BitTorrent::TorrentCreatorThread *m_creatorThread;
Expand All @@ -81,6 +83,7 @@ private slots:
CachedSettingValue<bool> m_storeStartSeeding;
CachedSettingValue<bool> m_storeIgnoreRatio;
CachedSettingValue<bool> m_storeOptimizeAlignment;
CachedSettingValue<int> m_paddedFileSizeLimit;
CachedSettingValue<QString> m_storeLastAddPath;
CachedSettingValue<QString> m_storeTrackerList;
CachedSettingValue<QString> m_storeWebSeedList;
Expand Down
53 changes: 49 additions & 4 deletions src/gui/torrentcreatordialog.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>592</width>
<height>658</height>
<height>731</height>
</rect>
</property>
<property name="acceptDrops">
Expand Down Expand Up @@ -225,13 +225,58 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkOptimizeAlignment">
<property name="text">
<widget class="QGroupBox" name="checkOptimizeAlignment">
<property name="title">
<string>Optimize alignment</string>
</property>
<property name="checked">
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="lblPaddedFileSizeLimit">
<property name="text">
<string>Align to piece boundary for files larger than:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinPaddedFileSizeLimit">
<property name="specialValueText">
<string>Disabled</string>
</property>
<property name="suffix">
<string> KiB</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>2147483647</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
Expand Down

0 comments on commit edcc74c

Please sign in to comment.