fix: replace retained report sessions when re-adding queue items
This commit is contained in:
@@ -40,8 +40,9 @@ Player *player_create(void);
|
||||
// Opt-in reporting must be initialized before opening media. Creates a new 0600
|
||||
// file exclusively; errors never change playback state. Error buffers hold 512 bytes.
|
||||
bool player_set_progress_file(Player *player, const char *path, char *error);
|
||||
// Register immutable queue destinations without changing current playback. Each path is new;
|
||||
// revisits append only to the original owned inode. Conflicting identities/paths are rejected.
|
||||
// Register queue destinations without changing playback. Each path is new and stays reserved.
|
||||
// A fresh path replaces an identity's previous session after draining its writer; callers
|
||||
// reject identities still queued. Revisits append only to the registered session's owned inode.
|
||||
// Atomic batch: all registrations succeed or none do. Strings are copied before returning.
|
||||
bool player_register_progress_files(Player *player, const char *const *identities,
|
||||
const char *const *paths, int count, char *error);
|
||||
|
||||
@@ -305,20 +305,34 @@ void ProgressReports::registerFile(const std::string &identity, const std::strin
|
||||
void ProgressReports::registerFiles(const char *const *identities, const char *const *destinations, int count) {
|
||||
std::lock_guard lock(mutex);
|
||||
if (!identities || !destinations || count < 1 || count > 4096 ||
|
||||
entries.size() + count > 4096)
|
||||
paths.size() + count > 4096)
|
||||
throw std::runtime_error("Queue reports exceed the 4096 retained registration limit");
|
||||
std::map<std::string, Entry> additions;
|
||||
std::set<std::string> newPaths;
|
||||
for (int index = 0; index < count; ++index) {
|
||||
const auto *identity = identities[index], *path = destinations[index];
|
||||
if (!identity || !path || !ProgressReporter::validMediaIdentity(identity) ||
|
||||
!*path || *path != '/' || singleIdentity == identity || entries.contains(identity) || additions.contains(identity))
|
||||
!*path || *path != '/' || additions.contains(identity))
|
||||
throw std::runtime_error("Invalid or conflicting queue progress identity");
|
||||
if (singlePath == path || paths.contains(path) || !newPaths.insert(path).second)
|
||||
throw std::runtime_error("Conflicting queue progress report path");
|
||||
additions.emplace(identity, Entry{path, nullptr});
|
||||
}
|
||||
// Node merges allocate nothing: failed validation cannot partially register a batch.
|
||||
// Validate and allocate the whole batch before retiring any previous sessions.
|
||||
auto retire = [this](ProgressReporter *reporter) {
|
||||
if (!reporter) return;
|
||||
reporter->finish();
|
||||
if (active == reporter) active = nullptr;
|
||||
try { if (failure.empty()) failure = reporter->error(); } catch (...) {}
|
||||
};
|
||||
for (auto &[identity, entry] : additions) {
|
||||
if (singleIdentity == identity) retire(single.get());
|
||||
if (auto found = entries.find(identity); found != entries.end()) {
|
||||
retire(found->second.reporter.get());
|
||||
std::swap(found->second, entry);
|
||||
}
|
||||
}
|
||||
// Node merges allocate nothing; replaced nodes remain in additions for destruction.
|
||||
entries.merge(additions);
|
||||
paths.merge(newPaths);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user