refactor: tidy libtransmission symbol visibility (#4680)

This commit is contained in:
Charles Kerr 2023-01-27 14:25:08 -06:00 committed by GitHub
parent 568b23374c
commit c75f9a4a7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 96 additions and 103 deletions

View File

@ -119,8 +119,6 @@ public:
void setParent(tr_bandwidth* new_parent); void setParent(tr_bandwidth* new_parent);
void deparent() noexcept;
[[nodiscard]] constexpr tr_priority_t getPriority() const noexcept [[nodiscard]] constexpr tr_priority_t getPriority() const noexcept
{ {
return this->priority_; return this->priority_;
@ -140,7 +138,7 @@ public:
} }
/** @brief Get the raw total of bytes read or sent by this bandwidth subtree. */ /** @brief Get the raw total of bytes read or sent by this bandwidth subtree. */
[[nodiscard]] tr_bytes_per_second_t getRawSpeedBytesPerSecond(uint64_t const now, tr_direction const dir) const [[nodiscard]] auto getRawSpeedBytesPerSecond(uint64_t const now, tr_direction const dir) const
{ {
TR_ASSERT(tr_isDirection(dir)); TR_ASSERT(tr_isDirection(dir));
@ -148,7 +146,7 @@ public:
} }
/** @brief Get the number of piece data bytes read or sent by this bandwidth subtree. */ /** @brief Get the number of piece data bytes read or sent by this bandwidth subtree. */
[[nodiscard]] tr_bytes_per_second_t getPieceSpeedBytesPerSecond(uint64_t const now, tr_direction const dir) const [[nodiscard]] auto getPieceSpeedBytesPerSecond(uint64_t const now, tr_direction const dir) const
{ {
TR_ASSERT(tr_isDirection(dir)); TR_ASSERT(tr_isDirection(dir));
@ -168,6 +166,15 @@ public:
return did_change; return did_change;
} }
/**
* @brief Get the desired speed for the bandwidth subtree.
* @see `tr_bandwidth::setDesiredSpeed`
*/
[[nodiscard]] constexpr auto getDesiredSpeedBytesPerSecond(tr_direction dir) const
{
return this->band_[dir].desired_speed_bps_;
}
[[nodiscard]] bool is_maxed_out(tr_direction dir, uint64_t now_msec) const noexcept [[nodiscard]] bool is_maxed_out(tr_direction dir, uint64_t now_msec) const noexcept
{ {
if (!isLimited(dir)) if (!isLimited(dir))
@ -180,15 +187,6 @@ public:
return got >= want; return got >= want;
} }
/**
* @brief Get the desired speed for the bandwidth subtree.
* @see `tr_bandwidth::setDesiredSpeed`
*/
[[nodiscard]] constexpr tr_bytes_per_second_t getDesiredSpeedBytesPerSecond(tr_direction dir) const
{
return this->band_[dir].desired_speed_bps_;
}
/** /**
* @brief Set whether or not this bandwidth should throttle its peer-io's speeds * @brief Set whether or not this bandwidth should throttle its peer-io's speeds
*/ */
@ -229,6 +227,11 @@ public:
return this->band_[direction].honor_parent_limits_; return this->band_[direction].honor_parent_limits_;
} }
[[nodiscard]] tr_bandwidth_limits getLimits() const;
void setLimits(tr_bandwidth_limits const* limits);
private:
struct RateControl struct RateControl
{ {
std::array<uint64_t, HistorySize> date_; std::array<uint64_t, HistorySize> date_;
@ -248,17 +251,14 @@ public:
bool honor_parent_limits_ = true; bool honor_parent_limits_ = true;
}; };
[[nodiscard]] tr_bandwidth_limits getLimits() const; static tr_bytes_per_second_t getSpeedBytesPerSecond(RateControl& r, unsigned int interval_msec, uint64_t now);
void setLimits(tr_bandwidth_limits const* limits);
[[nodiscard]] constexpr auto* parent() noexcept [[nodiscard]] constexpr auto* parent() noexcept
{ {
return parent_; return parent_;
} }
private: void deparent() noexcept;
static tr_bytes_per_second_t getSpeedBytesPerSecond(RateControl& r, unsigned int interval_msec, uint64_t now);
static void notifyBandwidthConsumedBytes(uint64_t now, RateControl* r, size_t size); static void notifyBandwidthConsumedBytes(uint64_t now, RateControl* r, size_t size);

View File

@ -228,11 +228,6 @@ bool tr_bitfield::ensureNthBitAlloced(size_t nth)
return true; return true;
} }
void tr_bitfield::freeArray() noexcept
{
flags_ = std::vector<uint8_t>{};
}
void tr_bitfield::setTrueCount(size_t n) noexcept void tr_bitfield::setTrueCount(size_t n) noexcept
{ {
TR_ASSERT(bit_count_ == 0 || n <= bit_count_); TR_ASSERT(bit_count_ == 0 || n <= bit_count_);
@ -249,11 +244,6 @@ void tr_bitfield::setTrueCount(size_t n) noexcept
TR_ASSERT(isValid()); TR_ASSERT(isValid());
} }
void tr_bitfield::rebuildTrueCount() noexcept
{
setTrueCount(countFlags());
}
void tr_bitfield::incrementTrueCount(size_t inc) noexcept void tr_bitfield::incrementTrueCount(size_t inc) noexcept
{ {
TR_ASSERT(bit_count_ == 0 || inc <= bit_count_); TR_ASSERT(bit_count_ == 0 || inc <= bit_count_);

View File

@ -132,12 +132,20 @@ private:
void ensureBitsAlloced(size_t n); void ensureBitsAlloced(size_t n);
[[nodiscard]] bool ensureNthBitAlloced(size_t nth); [[nodiscard]] bool ensureNthBitAlloced(size_t nth);
void freeArray() noexcept;
void setTrueCount(size_t n) noexcept; void freeArray() noexcept
void rebuildTrueCount() noexcept; {
// move-assign to ensure the reserve memory is cleared
flags_ = std::vector<uint8_t>{};
}
void incrementTrueCount(size_t inc) noexcept; void incrementTrueCount(size_t inc) noexcept;
void decrementTrueCount(size_t dec) noexcept; void decrementTrueCount(size_t dec) noexcept;
void setTrueCount(size_t n) noexcept;
void rebuildTrueCount() noexcept
{
setTrueCount(countFlags());
}
std::vector<uint8_t> flags_; std::vector<uint8_t> flags_;

View File

@ -94,17 +94,6 @@ void tr_completion::amountDone(float* tab, size_t n_tabs) const
} }
} }
size_t tr_completion::countMissingBlocksInPiece(tr_piece_index_t piece) const
{
auto const [begin, end] = block_info_->blockSpanForPiece(piece);
return (end - begin) - blocks_.count(begin, end);
}
size_t tr_completion::countMissingBytesInPiece(tr_piece_index_t piece) const
{
return block_info_->pieceSize(piece) - countHasBytesInPiece(piece);
}
std::vector<uint8_t> tr_completion::createPieceBitfield() const std::vector<uint8_t> tr_completion::createPieceBitfield() const
{ {
size_t const n = block_info_->pieceCount(); size_t const n = block_info_->pieceCount();

View File

@ -118,8 +118,16 @@ struct tr_completion
[[nodiscard]] std::vector<uint8_t> createPieceBitfield() const; [[nodiscard]] std::vector<uint8_t> createPieceBitfield() const;
[[nodiscard]] size_t countMissingBlocksInPiece(tr_piece_index_t) const; [[nodiscard]] size_t countMissingBlocksInPiece(tr_piece_index_t piece) const
[[nodiscard]] size_t countMissingBytesInPiece(tr_piece_index_t) const; {
auto const [begin, end] = block_info_->blockSpanForPiece(piece);
return (end - begin) - blocks_.count(begin, end);
}
[[nodiscard]] size_t countMissingBytesInPiece(tr_piece_index_t piece) const
{
return block_info_->pieceSize(piece) - countHasBytesInPiece(piece);
}
void amountDone(float* tab, size_t n_tabs) const; void amountDone(float* tab, size_t n_tabs) const;

View File

@ -417,6 +417,8 @@ void tr_net_close_socket(tr_socket_t sockfd)
evutil_closesocket(sockfd); evutil_closesocket(sockfd);
} }
namespace
{
// code in global_ipv6_herlpers is written by Juliusz Chroboczek // code in global_ipv6_herlpers is written by Juliusz Chroboczek
// and is covered under the same license as dht.cc. // and is covered under the same license as dht.cc.
// Please feel free to copy them into your software if it can help // Please feel free to copy them into your software if it can help
@ -482,6 +484,7 @@ namespace global_ipv6_helpers
} }
} // namespace global_ipv6_helpers } // namespace global_ipv6_helpers
} // namespace
/* Return our global IPv6 address, with caching. */ /* Return our global IPv6 address, with caching. */
std::optional<tr_address> tr_globalIPv6() std::optional<tr_address> tr_globalIPv6()
@ -503,6 +506,8 @@ std::optional<tr_address> tr_globalIPv6()
// --- // ---
namespace
{
namespace is_valid_for_peers_helpers namespace is_valid_for_peers_helpers
{ {
@ -543,6 +548,7 @@ namespace is_valid_for_peers_helpers
} }
} // namespace is_valid_for_peers_helpers } // namespace is_valid_for_peers_helpers
} // namespace
bool tr_address::is_valid_for_peers(tr_port port) const noexcept bool tr_address::is_valid_for_peers(tr_port port) const noexcept
{ {
@ -694,21 +700,16 @@ std::pair<sockaddr_storage, socklen_t> tr_address::to_sockaddr(tr_port port) con
return { ss, sizeof(sockaddr_in6) }; return { ss, sizeof(sockaddr_in6) };
} }
static int tr_address_compare(tr_address const* a, tr_address const* b) noexcept // <=>
{
// IPv6 addresses are always "greater than" IPv4
if (a->type != b->type)
{
return a->is_ipv4() ? 1 : -1;
}
return a->is_ipv4() ? memcmp(&a->addr.addr4, &b->addr.addr4, sizeof(a->addr.addr4)) :
memcmp(&a->addr.addr6.s6_addr, &b->addr.addr6.s6_addr, sizeof(a->addr.addr6.s6_addr));
}
int tr_address::compare(tr_address const& that) const noexcept // <=> int tr_address::compare(tr_address const& that) const noexcept // <=>
{ {
return tr_address_compare(this, &that); // IPv6 addresses are always "greater than" IPv4
if (this->type != that.type)
{
return this->is_ipv4() ? 1 : -1;
}
return this->is_ipv4() ? memcmp(&this->addr.addr4, &that.addr.addr4, sizeof(this->addr.addr4)) :
memcmp(&this->addr.addr6.s6_addr, &that.addr.addr6.s6_addr, sizeof(this->addr.addr6.s6_addr));
} }
// https://en.wikipedia.org/wiki/Reserved_IP_addresses // https://en.wikipedia.org/wiki/Reserved_IP_addresses

View File

@ -1233,6 +1233,8 @@ void tr_peerMgrGotBadPiece(tr_torrent* tor, tr_piece_index_t piece_index)
tr_announcerAddBytes(tor, TR_ANN_CORRUPT, byte_count); tr_announcerAddBytes(tor, TR_ANN_CORRUPT, byte_count);
} }
namespace
{
namespace get_peers_helpers namespace get_peers_helpers
{ {
@ -1296,6 +1298,7 @@ struct CompareAtomsByUsefulness
} }
} // namespace get_peers_helpers } // namespace get_peers_helpers
} // namespace
std::vector<tr_pex> tr_peerMgrGetPeers(tr_torrent const* tor, uint8_t address_type, uint8_t list_mode, size_t max_peer_count) std::vector<tr_pex> tr_peerMgrGetPeers(tr_torrent const* tor, uint8_t address_type, uint8_t list_mode, size_t max_peer_count)
{ {
@ -1533,6 +1536,8 @@ tr_webseed_view tr_peerMgrWebseed(tr_torrent const* tor, size_t i)
return i >= n ? tr_webseed_view{} : tr_webseedView(tor->swarm->webseeds[i].get()); return i >= n ? tr_webseed_view{} : tr_webseedView(tor->swarm->webseeds[i].get());
} }
namespace
{
namespace peer_stat_helpers namespace peer_stat_helpers
{ {
@ -1634,6 +1639,7 @@ namespace peer_stat_helpers
} }
} // namespace peer_stat_helpers } // namespace peer_stat_helpers
} // namespace
tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, size_t* setme_count) tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, size_t* setme_count)
{ {
@ -1666,11 +1672,10 @@ void tr_peerMgrClearInterest(tr_torrent* tor)
std::for_each(std::begin(peers), std::end(peers), [](auto* const peer) { peer->set_interested(false); }); std::for_each(std::begin(peers), std::end(peers), [](auto* const peer) { peer->set_interested(false); });
} }
namespace rechoke_downloads_helpers
{
namespace namespace
{ {
namespace rechoke_downloads_helpers
{
/* does this peer have any pieces that we want? */ /* does this peer have any pieces that we want? */
[[nodiscard]] bool isPeerInteresting( [[nodiscard]] bool isPeerInteresting(
tr_torrent const* const tor, tr_torrent const* const tor,
@ -1738,8 +1743,6 @@ struct tr_rechoke_info
uint8_t salt; uint8_t salt;
}; };
} // namespace
/* determines who we send "interested" messages to */ /* determines who we send "interested" messages to */
void rechokeDownloads(tr_swarm* s) void rechokeDownloads(tr_swarm* s)
{ {
@ -1896,16 +1899,15 @@ void rechokeDownloads(tr_swarm* s)
rechoke[i].peer->set_interested(i < s->interested_count); rechoke[i].peer->set_interested(i < s->interested_count);
} }
} }
} // namespace rechoke_downloads_helpers } // namespace rechoke_downloads_helpers
} // namespace
// --- // ---
namespace rechoke_uploads_helpers
{
namespace namespace
{ {
namespace rechoke_uploads_helpers
{
struct ChokeData struct ChokeData
{ {
ChokeData(tr_peerMsgs* msgs_in, int rate_in, uint8_t salt_in, bool is_interested_in, bool was_choked_in, bool is_choked_in) ChokeData(tr_peerMsgs* msgs_in, int rate_in, uint8_t salt_in, bool is_interested_in, bool was_choked_in, bool is_choked_in)
@ -1975,8 +1977,6 @@ struct ChokeData
// for this many calls to rechokeUploads(). // for this many calls to rechokeUploads().
auto constexpr OptimisticUnchokeMultiplier = uint8_t{ 4 }; auto constexpr OptimisticUnchokeMultiplier = uint8_t{ 4 };
} // namespace
void rechokeUploads(tr_swarm* s, uint64_t const now) void rechokeUploads(tr_swarm* s, uint64_t const now)
{ {
auto const lock = s->unique_lock(); auto const lock = s->unique_lock();
@ -2090,8 +2090,8 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
item.msgs->set_choke(item.is_choked); item.msgs->set_choke(item.is_choked);
} }
} }
} // namespace rechoke_uploads_helpers } // namespace rechoke_uploads_helpers
} // namespace
void tr_peerMgr::rechokePulse() const void tr_peerMgr::rechokePulse() const
{ {
@ -2122,10 +2122,10 @@ void tr_peerMgr::rechokePulse() const
// --- Life and Death // --- Life and Death
namespace disconnect_helpers
{
namespace namespace
{ {
namespace disconnect_helpers
{
// when many peers are available, keep idle ones this long // when many peers are available, keep idle ones this long
auto constexpr MinUploadIdleSecs = time_t{ 60 }; auto constexpr MinUploadIdleSecs = time_t{ 60 };
@ -2248,8 +2248,6 @@ struct ComparePeerByActivity
return peers_to_close; return peers_to_close;
} }
} // namespace
void closeBadPeers(tr_swarm* s, time_t const now_sec) void closeBadPeers(tr_swarm* s, time_t const now_sec)
{ {
for (auto* peer : getPeersToClose(s, now_sec)) for (auto* peer : getPeersToClose(s, now_sec))
@ -2296,8 +2294,8 @@ void enforceSessionPeerLimit(tr_session* session)
std::for_each(std::begin(peers) + max, std::end(peers), closePeer); std::for_each(std::begin(peers) + max, std::end(peers), closePeer);
} }
} }
} // namespace disconnect_helpers } // namespace disconnect_helpers
} // namespace
void tr_peerMgr::reconnectPulse() void tr_peerMgr::reconnectPulse()
{ {
@ -2340,6 +2338,8 @@ void tr_peerMgr::reconnectPulse()
// --- Bandwidth Allocation // --- Bandwidth Allocation
namespace
{
namespace bandwidth_helpers namespace bandwidth_helpers
{ {
@ -2373,6 +2373,7 @@ void queuePulse(tr_session* session, tr_direction dir)
} }
} // namespace bandwidth_helpers } // namespace bandwidth_helpers
} // namespace
void tr_peerMgr::bandwidthPulse() void tr_peerMgr::bandwidthPulse()
{ {
@ -2405,11 +2406,10 @@ bool tr_swarm::peer_is_in_use(peer_atom const& atom) const
manager->incoming_handshakes.count(atom.addr) != 0U; manager->incoming_handshakes.count(atom.addr) != 0U;
} }
namespace connect_helpers
{
namespace namespace
{ {
namespace connect_helpers
{
/* is this atom someone that we'd want to initiate a connection to? */ /* is this atom someone that we'd want to initiate a connection to? */
[[nodiscard]] bool isPeerCandidate(tr_torrent const* tor, peer_atom const& atom, time_t const now) [[nodiscard]] bool isPeerCandidate(tr_torrent const* tor, peer_atom const& atom, time_t const now)
{ {
@ -2530,8 +2530,6 @@ struct peer_candidate
return score; return score;
} }
} // namespace
/** @return an array of all the atoms we might want to connect to */ /** @return an array of all the atoms we might want to connect to */
[[nodiscard]] std::vector<peer_candidate> getPeerCandidates(tr_session* session, size_t max) [[nodiscard]] std::vector<peer_candidate> getPeerCandidates(tr_session* session, size_t max)
{ {
@ -2655,8 +2653,8 @@ void initiateConnection(tr_peerMgr* mgr, tr_swarm* s, peer_atom& atom)
atom.lastConnectionAttemptAt = now; atom.lastConnectionAttemptAt = now;
atom.time = now; atom.time = now;
} }
} // namespace connect_helpers } // namespace connect_helpers
} // namespace
void tr_peerMgr::makeNewPeerConnections(size_t max) void tr_peerMgr::makeNewPeerConnections(size_t max)
{ {

View File

@ -16,6 +16,8 @@
using namespace std::literals; using namespace std::literals;
namespace
{
namespace wi namespace wi
{ {
using key_t = math::wide_integer::uintwide_t< using key_t = math::wide_integer::uintwide_t<
@ -61,6 +63,7 @@ auto WIDE_INTEGER_CONSTEXPR const prime = wi::key_t{
// NOLINTEND(readability-identifier-naming) // NOLINTEND(readability-identifier-naming)
} // namespace wi } // namespace wi
} // namespace
namespace tr_message_stream_encryption namespace tr_message_stream_encryption
{ {

View File

@ -23,12 +23,15 @@
using namespace std::literals; using namespace std::literals;
namespace
{
struct optional_args struct optional_args
{ {
std::optional<bool> paused; std::optional<bool> paused;
std::optional<uint16_t> peer_limit; std::optional<uint16_t> peer_limit;
std::string download_dir; std::string download_dir;
}; };
} // namespace
/** Opaque class used when instantiating torrents. /** Opaque class used when instantiating torrents.
* @ingroup tr_ctor */ * @ingroup tr_ctor */

View File

@ -28,11 +28,14 @@
#include "utils.h" #include "utils.h"
#include "variant.h" #include "variant.h"
namespace
{
struct metadata_node struct metadata_node
{ {
time_t requested_at = 0U; time_t requested_at = 0U;
int piece = 0; int piece = 0;
}; };
} // namespace
struct tr_incomplete_metadata struct tr_incomplete_metadata
{ {

View File

@ -53,12 +53,15 @@ std::string tr_torrent_metainfo::fixWebseedUrl(tr_torrent_metainfo const& tm, st
return std::string{ url }; return std::string{ url };
} }
static auto constexpr MaxBencDepth = 32; namespace
{
auto constexpr MaxBencDepth = 32;
bool tr_error_is_set(tr_error const* const* error) bool tr_error_is_set(tr_error const* const* error)
{ {
return (error != nullptr) && (*error != nullptr); return (error != nullptr) && (*error != nullptr);
} }
} // namespace
struct MetainfoHandler final : public transmission::benc::BasicHandler<MaxBencDepth> struct MetainfoHandler final : public transmission::benc::BasicHandler<MaxBencDepth>
{ {
@ -631,11 +634,6 @@ bool tr_torrent_metainfo::parseTorrentFile(std::string_view filename, std::vecto
return tr_loadFile(filename, *contents, error) && parseBenc({ std::data(*contents), std::size(*contents) }, error); return tr_loadFile(filename, *contents, error) && parseBenc({ std::data(*contents), std::size(*contents) }, error);
} }
tr_sha1_digest_t const& tr_torrent_metainfo::pieceHash(tr_piece_index_t piece) const
{
return this->pieces_[piece];
}
tr_pathbuf tr_torrent_metainfo::makeFilename( tr_pathbuf tr_torrent_metainfo::makeFilename(
std::string_view dirname, std::string_view dirname,
std::string_view name, std::string_view name,

View File

@ -128,7 +128,10 @@ public:
return is_private_; return is_private_;
} }
[[nodiscard]] tr_sha1_digest_t const& pieceHash(tr_piece_index_t piece) const; [[nodiscard]] TR_CONSTEXPR20 tr_sha1_digest_t const& pieceHash(tr_piece_index_t piece) const
{
return pieces_[piece];
}
[[nodiscard]] TR_CONSTEXPR20 bool hasV1Metadata() const noexcept [[nodiscard]] TR_CONSTEXPR20 bool hasV1Metadata() const noexcept
{ {

View File

@ -25,8 +25,6 @@ namespace libtransmission
class Buffer class Buffer
{ {
public: public:
using Iovec = evbuffer_iovec;
class Iterator class Iterator
{ {
public: public:
@ -132,7 +130,7 @@ public:
evbuffer* buf_; evbuffer* buf_;
evbuffer_ptr ptr_ = {}; evbuffer_ptr ptr_ = {};
Iovec iov_ = {}; evbuffer_iovec iov_ = {};
size_t iov_offset_ = 0; size_t iov_offset_ = 0;
}; };
@ -247,23 +245,11 @@ public:
return 0; return 0;
} }
[[nodiscard]] Iovec alloc(size_t n_bytes)
{
auto iov = Iovec{};
evbuffer_reserve_space(buf_.get(), static_cast<ev_ssize_t>(n_bytes), &iov, 1);
return iov;
}
[[nodiscard]] std::pair<std::byte*, size_t> pullup() [[nodiscard]] std::pair<std::byte*, size_t> pullup()
{ {
return { reinterpret_cast<std::byte*>(evbuffer_pullup(buf_.get(), -1)), size() }; return { reinterpret_cast<std::byte*>(evbuffer_pullup(buf_.get(), -1)), size() };
} }
void commit(Iovec iov)
{
evbuffer_commit_space(buf_.get(), &iov, 1);
}
void reserve(size_t n_bytes) void reserve(size_t n_bytes)
{ {
evbuffer_expand(buf_.get(), n_bytes - size()); evbuffer_expand(buf_.get(), n_bytes - size());

View File

@ -204,7 +204,7 @@ constexpr std::string_view getPortForScheme(std::string_view scheme)
return "-1"sv; return "-1"sv;
} }
bool urlCharsAreValid(std::string_view url) TR_CONSTEXPR20 bool urlCharsAreValid(std::string_view url)
{ {
// rfc2396 // rfc2396
auto constexpr ValidChars = std::string_view{ auto constexpr ValidChars = std::string_view{

View File

@ -43,6 +43,8 @@ using namespace std::literals;
// --- // ---
namespace
{
namespace curl_helpers namespace curl_helpers
{ {
@ -92,6 +94,7 @@ struct EasyDeleter
using easy_unique_ptr = std::unique_ptr<CURL, EasyDeleter>; using easy_unique_ptr = std::unique_ptr<CURL, EasyDeleter>;
} // namespace curl_helpers } // namespace curl_helpers
} // namespace
#ifdef _WIN32 #ifdef _WIN32
static CURLcode ssl_context_func(CURL* /*curl*/, void* ssl_ctx, void* /*user_data*/) static CURLcode ssl_context_func(CURL* /*curl*/, void* ssl_ctx, void* /*user_data*/)