m_temp_transid.erase(fid);
}
+string
+BeesContext::temp_transid_report()
+{
+ ostringstream oss;
+ unique_lock<mutex> lock(m_temp_transid_mutex);
+ for (const auto &[fid, transid] : m_temp_transid) {
+ oss << " " << fid << "@" << transid;
+ }
+ return oss.str();
+}
+
uint64_t
BeesContext::temp_transid_min()
{
if (limit < rv) {
rv = limit;
BEESCOUNT(crawl_temp_transid_hold);
+ // A hold is normal while dedupe is in flight, but a
+ // hold that persists with idle workers means a temp
+ // file was never returned to its pool (something still
+ // holds its BeesTempExtent). Name the holders, rate
+ // limited, so the retainer can be identified from the
+ // log. Debug level: bees handles the hold itself;
+ // operators do not need to act on it.
+ static RateLimiter s_hold_report_limit(1.0 / 60);
+ if (s_hold_report_limit.is_ready()) {
+ BEESLOGDEBUG("crawl held below transid "
+ << temp_floor << " by temp file(s):"
+ << m_ctx->temp_transid_report());
+ }
}
}
return rv;
void temp_transid_erase(const BeesFileId &fid);
/// Earliest transid among live temp files, or 0 when none hold data.
uint64_t temp_transid_min();
+ /// Describe the registered temp-file transid holds (fid and
+ /// transid of each entry) for hold diagnostics. Empty string
+ /// when no entries are registered.
+ std::string temp_transid_report();
/// Return the per-inode Exclusion mutex for @p inode (creates if absent).
shared_ptr<Exclusion> get_inode_mutex(uint64_t inode);