refactor: avoid referencing tr_file struct directly (#2373)

This commit is contained in:
Charles Kerr
2022-01-01 19:25:25 -06:00
committed by GitHub
parent e56997185e
commit eafbf59832
7 changed files with 82 additions and 83 deletions

View File

@@ -45,19 +45,19 @@ static int readOrWriteBytes(
tr_session* session,
tr_torrent* tor,
int ioMode,
tr_file_index_t fileIndex,
uint64_t fileOffset,
tr_file_index_t file_index,
uint64_t file_offset,
void* buf,
size_t buflen)
{
int err = 0;
bool const doWrite = ioMode >= TR_IO_WRITE;
auto const& file = tor->file(fileIndex);
TR_ASSERT(file.length == 0 || fileOffset < file.length);
TR_ASSERT(fileOffset + buflen <= file.length);
auto const file_size = tor->fileSize(file_index);
TR_ASSERT(file_size == 0 || file_offset < file_size);
TR_ASSERT(file_offset + buflen <= file_size);
if (file.length == 0)
if (file_size == 0)
{
return 0;
}
@@ -66,14 +66,14 @@ static int readOrWriteBytes(
**** Find the fd
***/
tr_sys_file_t fd = tr_fdFileGetCached(session, tr_torrentId(tor), fileIndex, doWrite);
auto fd = tr_fdFileGetCached(session, tr_torrentId(tor), file_index, doWrite);
if (fd == TR_BAD_SYS_FILE) /* it's not cached, so open/create it now */
{
/* see if the file exists... */
char const* base = nullptr;
char* subpath = nullptr;
if (!tr_torrentFindFile2(tor, fileIndex, &base, &subpath, nullptr))
if (!tr_torrentFindFile2(tor, file_index, &base, &subpath, nullptr))
{
/* we can't read a file that doesn't exist... */
if (!doWrite)
@@ -83,19 +83,18 @@ static int readOrWriteBytes(
/* figure out where the file should go, so we can create it */
base = tr_torrentGetCurrentDir(tor);
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, fileIndex) :
tr_strdup(file.name);
subpath = tr_sessionIsIncompleteFileNamingEnabled(tor->session) ? tr_torrentBuildPartial(tor, file_index) :
tr_strvDup(tor->fileSubpath(file_index));
}
if (err == 0)
{
/* open (and maybe create) the file */
auto const filename = tr_strvPath(base, subpath);
tr_preallocation_mode const prealloc = (!doWrite || !tor->fileIsWanted(fileIndex)) ?
TR_PREALLOCATE_NONE :
tor->session->preallocationMode;
auto const prealloc = (!doWrite || !tor->fileIsWanted(file_index)) ? TR_PREALLOCATE_NONE :
tor->session->preallocationMode;
fd = tr_fdFileCheckout(session, tor->uniqueId, fileIndex, filename.c_str(), doWrite, prealloc, file.length);
fd = tr_fdFileCheckout(session, tor->uniqueId, file_index, filename.c_str(), doWrite, prealloc, file_size);
if (fd == TR_BAD_SYS_FILE)
{
err = errno;
@@ -121,25 +120,25 @@ static int readOrWriteBytes(
if (ioMode == TR_IO_READ)
{
if (!tr_sys_file_read_at(fd, buf, buflen, fileOffset, nullptr, &error))
if (!tr_sys_file_read_at(fd, buf, buflen, file_offset, nullptr, &error))
{
err = error->code;
tr_logAddTorErr(tor, "read failed for \"%s\": %s", file.name, error->message);
tr_logAddTorErr(tor, "read failed for \"%s\": %s", tor->fileSubpath(file_index), error->message);
tr_error_free(error);
}
}
else if (ioMode == TR_IO_WRITE)
{
if (!tr_sys_file_write_at(fd, buf, buflen, fileOffset, nullptr, &error))
if (!tr_sys_file_write_at(fd, buf, buflen, file_offset, nullptr, &error))
{
err = error->code;
tr_logAddTorErr(tor, "write failed for \"%s\": %s", file.name, error->message);
tr_logAddTorErr(tor, "write failed for \"%s\": %s", tor->fileSubpath(file_index), error->message);
tr_error_free(error);
}
}
else if (ioMode == TR_IO_PREFETCH)
{
tr_sys_file_advise(fd, fileOffset, buflen, TR_SYS_FILE_ADVICE_WILL_NEED, nullptr);
tr_sys_file_advise(fd, file_offset, buflen, TR_SYS_FILE_ADVICE_WILL_NEED, nullptr);
}
else
{
@@ -166,22 +165,21 @@ static int readOrWritePiece(
return EINVAL;
}
auto [fileIndex, fileOffset] = tor->fileOffset(pieceIndex, pieceOffset);
auto [file_index, file_offset] = tor->fileOffset(pieceIndex, pieceOffset);
while (buflen != 0 && err == 0)
{
auto const& file = tor->file(fileIndex);
uint64_t const bytesThisPass = std::min(uint64_t{ buflen }, uint64_t{ file.length - fileOffset });
uint64_t const bytes_this_pass = std::min(uint64_t{ buflen }, uint64_t{ tor->fileSize(file_index) - file_offset });
err = readOrWriteBytes(tor->session, tor, ioMode, fileIndex, fileOffset, buf, bytesThisPass);
buf += bytesThisPass;
buflen -= bytesThisPass;
fileIndex++;
fileOffset = 0;
err = readOrWriteBytes(tor->session, tor, ioMode, file_index, file_offset, buf, bytes_this_pass);
buf += bytes_this_pass;
buflen -= bytes_this_pass;
++file_index;
file_offset = 0;
if (err != 0 && ioMode == TR_IO_WRITE && tor->error != TR_STAT_LOCAL_ERROR)
{
auto const path = tr_strvPath(tor->downloadDir().sv(), file.name);
auto const path = tr_strvPath(tor->downloadDir().sv(), tor->fileSubpath(file_index));
tor->setLocalError(tr_strvJoin(tr_strerror(err), " ("sv, path, ")"sv));
}
}

View File

@@ -403,7 +403,7 @@ static void saveFilenames(tr_variant* dict, tr_torrent const* tor)
tr_variant* const list = tr_variantDictAddList(dict, TR_KEY_files, n);
for (tr_file_index_t i = 0; i < n; ++i)
{
tr_variantListAddStrView(list, tor->file(i).name);
tr_variantListAddStrView(list, tor->fileSubpath(i));
}
}
@@ -420,11 +420,9 @@ static uint64_t loadFilenames(tr_variant* dict, tr_torrent* tor)
for (size_t i = 0; i < n_files && i < n_list; ++i)
{
auto sv = std::string_view{};
auto& file = tor->file(i);
if (tr_variantGetStrView(tr_variantListChild(list, i), &sv) && !std::empty(sv) && sv != file.name)
if (tr_variantGetStrView(tr_variantListChild(list, i), &sv) && !std::empty(sv))
{
tr_free(file.name);
file.name = tr_strvDup(sv);
tor->setFileSubpath(i, sv);
}
}

View File

@@ -1109,19 +1109,18 @@ tr_file_view tr_torrentFile(tr_torrent const* tor, tr_file_index_t i)
{
TR_ASSERT(tr_isTorrent(tor));
auto const& file = tor->file(i);
auto const* const name = file.name;
auto const* subpath = tor->fileSubpath(i);
auto const priority = tor->file_priorities_.filePriority(i);
auto const wanted = tor->files_wanted_.fileWanted(i);
auto const length = file.length;
auto const length = tor->fileSize(i);
if (tor->completeness == TR_SEED || length == 0)
{
return { name, length, length, 1.0, priority, wanted };
return { subpath, length, length, 1.0, priority, wanted };
}
auto const have = tor->completion.countHasBytesInSpan(tor->fpm_.byteSpan(i));
return { name, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
return { subpath, have, length, have >= length ? 1.0 : have / double(length), priority, wanted };
}
size_t tr_torrentFileCount(tr_torrent const* torrent)
@@ -2186,7 +2185,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
for (tr_file_index_t f = 0, n = tor->fileCount(); f < n; ++f)
{
/* try to find the file, looking in the partial and download dirs */
auto filename = tr_strvPath(top, tor->file(f).name);
auto filename = tr_strvPath(top, tor->fileSubpath(f));
if (!tr_sys_path_exists(filename.c_str(), nullptr))
{
@@ -2201,7 +2200,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
/* if we found the file, move it */
if (!std::empty(filename))
{
auto target = tr_strvPath(tmpdir, tor->file(f).name);
auto target = tr_strvPath(tmpdir, tor->fileSubpath(f));
tr_moveFile(filename.c_str(), target.c_str(), nullptr);
files.emplace_back(target);
}
@@ -2258,7 +2257,7 @@ static void deleteLocalData(tr_torrent* tor, tr_fileFunc func)
for (tr_file_index_t f = 0, n = tor->fileCount(); f < n; ++f)
{
/* get the directory that this file goes in... */
auto const filename = tr_strvPath(top, tor->file(f).name);
auto const filename = tr_strvPath(top, tor->fileSubpath(f));
char* dir = tr_sys_path_dirname(filename.c_str(), nullptr);
if (dir == nullptr)
{
@@ -2358,7 +2357,7 @@ static void setLocationImpl(void* vdata)
* if the target directory runs out of space halfway through... */
for (tr_file_index_t i = 0, n = tor->fileCount(); !err && i < n; ++i)
{
auto const file_length = tor->file(i).length;
auto const file_size = tor->fileSize(i);
char const* oldbase = nullptr;
char* sub = nullptr;
@@ -2393,7 +2392,7 @@ static void setLocationImpl(void* vdata)
if (data->setme_progress != nullptr)
{
bytesHandled += file_length;
bytesHandled += file_size;
*data->setme_progress = bytesHandled / tor->totalSize();
}
}
@@ -2473,9 +2472,8 @@ std::string_view tr_torrent::primaryMimeType() const
auto size_per_mime_type = std::unordered_map<std::string_view, size_t>{};
for (tr_file_index_t i = 0, n = this->fileCount(); i < n; ++i)
{
auto const& file = this->file(i);
auto const mime_type = tr_get_mime_type_for_filename(file.name);
size_per_mime_type[mime_type] += file.length;
auto const mime_type = tr_get_mime_type_for_filename(this->fileSubpath(i));
size_per_mime_type[mime_type] += this->fileSize(i);
}
if (std::empty(size_per_mime_type))
@@ -2515,10 +2513,10 @@ static void tr_torrentFileCompleted(tr_torrent* tor, tr_file_index_t i)
char* sub = nullptr;
if (tr_torrentFindFile2(tor, i, &base, &sub, nullptr))
{
if (tr_file& file = tor->file(i); strcmp(sub, file.name) != 0)
if (char const* file_subpath = tor->fileSubpath(i); strcmp(sub, file_subpath) != 0)
{
auto const oldpath = tr_strvPath(base, sub);
auto const newpath = tr_strvPath(base, file.name);
auto const newpath = tr_strvPath(base, file_subpath);
tr_error* error = nullptr;
if (!tr_sys_path_rename(oldpath.c_str(), newpath.c_str(), &error))
@@ -2591,20 +2589,20 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& filename, tr_file_index_t i) const
{
tr_file const& file = this->file(i);
auto const subpath = std::string_view{ this->fileSubpath(i) };
auto file_info = tr_sys_path_info{};
if (!std::empty(this->downloadDir()))
{
auto const base = this->downloadDir().sv();
tr_buildBuf(filename, base, "/"sv, file.name);
tr_buildBuf(filename, base, "/"sv, subpath);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
{
return tr_found_file_t{ file_info, filename, base };
}
tr_buildBuf(filename, base, "/"sv, file.name, ".part"sv);
tr_buildBuf(filename, base, "/"sv, subpath, ".part"sv);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
{
return tr_found_file_t{ file_info, filename, base };
@@ -2615,13 +2613,13 @@ std::optional<tr_torrent::tr_found_file_t> tr_torrent::findFile(std::string& fil
{
auto const base = this->incompleteDir().sv();
tr_buildBuf(filename, base, "/"sv, file.name);
tr_buildBuf(filename, base, "/"sv, subpath);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
{
return tr_found_file_t{ file_info, filename, base };
}
tr_buildBuf(filename, base, "/"sv, file.name, ".part"sv);
tr_buildBuf(filename, base, "/"sv, subpath, ".part"sv);
if (tr_sys_path_get_info(filename.c_str(), 0, &file_info, nullptr))
{
return tr_found_file_t{ file_info, filename, base };
@@ -2696,7 +2694,7 @@ static void refreshCurrentDir(tr_torrent* tor)
char* tr_torrentBuildPartial(tr_torrent const* tor, tr_file_index_t i)
{
return tr_strvDup(tr_strvJoin(tor->file(i).name, ".part"sv));
return tr_strvDup(tr_strvJoin(tor->fileSubpath(i), ".part"sv));
}
/***
@@ -2870,7 +2868,7 @@ static tr_file_index_t* renameFindAffectedFiles(tr_torrent* tor, char const* old
for (tr_file_index_t i = 0; i < n_files; ++i)
{
char const* name = tor->file(i).name;
char const* name = tor->fileSubpath(i);
size_t const len = strlen(name);
if ((len == oldpath_len || (len > oldpath_len && name[oldpath_len] == '/')) && memcmp(oldpath, name, oldpath_len) == 0)
@@ -2927,21 +2925,21 @@ static int renamePath(tr_torrent* tor, char const* oldpath, char const* newname)
return err;
}
static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char const* newname, tr_file_index_t fileIndex)
static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char const* newname, tr_file_index_t file_index)
{
char* name = nullptr;
tr_file& file = tor->file(fileIndex);
size_t const oldpath_len = strlen(oldpath);
auto name = std::string{};
auto const subpath = std::string_view{ tor->fileSubpath(file_index) };
auto const oldpath_len = strlen(oldpath);
if (strchr(oldpath, TR_PATH_DELIMITER) == nullptr)
{
if (oldpath_len >= strlen(file.name))
if (oldpath_len >= std::size(subpath))
{
name = tr_buildPath(newname, nullptr);
name = tr_strvPath(newname);
}
else
{
name = tr_buildPath(newname, file.name + oldpath_len + 1, nullptr);
name = tr_strvPath(newname, subpath.substr(oldpath_len + 1));
}
}
else
@@ -2953,26 +2951,21 @@ static void renameTorrentFileString(tr_torrent* tor, char const* oldpath, char c
return;
}
if (oldpath_len >= strlen(file.name))
if (oldpath_len >= std::size(subpath))
{
name = tr_buildPath(tmp, newname, nullptr);
name = tr_strvPath(tmp, newname);
}
else
{
name = tr_buildPath(tmp, newname, file.name + oldpath_len + 1, nullptr);
name = tr_strvPath(tmp, newname, subpath.substr(oldpath_len + 1));
}
tr_free(tmp);
}
if (strcmp(file.name, name) == 0)
if (subpath != name)
{
tr_free(name);
}
else
{
tr_free(file.name);
file.name = name;
tor->setFileSubpath(file_index, name);
}
}
@@ -3138,3 +3131,13 @@ void tr_torrent::setName(std::string_view name)
tr_free(this->info.name);
this->info.name = tr_strvDup(name);
}
void tr_torrent::setFileSubpath(tr_file_index_t i, std::string_view subpath)
{
if (fileSubpath(i) != subpath)
{
auto* old = this->info.files[i].name;
this->info.files[i].name = tr_strvDup(subpath);
tr_free(old);
}
}

View File

@@ -317,20 +317,22 @@ public:
return info.fileCount;
}
[[nodiscard]] auto& file(tr_file_index_t i)
[[nodiscard]] char const* fileSubpath(tr_file_index_t i) const
{
TR_ASSERT(i < this->fileCount());
return info.files[i];
return info.files[i].name ? info.files[i].name : "";
}
[[nodiscard]] auto const& file(tr_file_index_t i) const
[[nodiscard]] auto fileSize(tr_file_index_t i) const
{
TR_ASSERT(i < this->fileCount());
return info.files[i];
return info.files[i].length;
}
void setFileSubpath(tr_file_index_t i, std::string_view subpath);
struct tr_found_file_t : public tr_sys_path_info
{
std::string& filename; // /home/foo/Downloads/torrent/01-file-one.txt

View File

@@ -54,7 +54,6 @@ struct tr_byte_span_t
struct tr_ctor;
struct tr_error;
struct tr_file;
struct tr_info;
struct tr_session;
struct tr_torrent;

View File

@@ -50,7 +50,7 @@ static bool verifyTorrent(tr_torrent* tor, bool* stopFlag)
while (!*stopFlag && piece < tor->pieceCount())
{
auto const file_length = tor->file(fileIndex).length;
auto const file_length = tor->fileSize(fileIndex);
/* if we're starting a new piece... */
if (piecePos == 0)

View File

@@ -491,14 +491,14 @@ static void web_response_func(
}
}
static std::string make_url(tr_webseed* w, char const* name)
static std::string make_url(tr_webseed* w, std::string_view name)
{
struct evbuffer* buf = evbuffer_new();
evbuffer_add(buf, std::data(w->base_url), std::size(w->base_url));
/* if url ends with a '/', add the torrent name */
if (*std::rbegin(w->base_url) == '/' && name != nullptr)
if (*std::rbegin(w->base_url) == '/' && !std::empty(name))
{
tr_http_escape(buf, name, false);
}
@@ -525,12 +525,11 @@ static void task_request_next_chunk(struct tr_webseed_task* t)
uint64_t const step_piece_offset = total_offset - uint64_t(piece_size) * step_piece;
auto const [file_index, file_offset] = tor->fileOffset(step_piece, step_piece_offset);
auto const& file = tor->file(file_index);
uint64_t this_pass = std::min(remain, file.length - file_offset);
uint64_t this_pass = std::min(remain, tor->fileSize(file_index) - file_offset);
if (std::empty(urls[file_index]))
{
urls[file_index] = make_url(t->webseed, file.name);
urls[file_index] = make_url(t->webseed, tor->fileSubpath(file_index));
}
char range[64];