mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 08:41:31 +00:00
[idd] scheduler: reserve slots for frame subscribers
Replace the oldest provisional schedule entry when the bounded client table has no empty slot. Never evict a client whose frame subscription has already been observed. This prevents rapid failed reconnects from filling every scheduler slot before a real frame subscriber can be registered.
This commit is contained in:
@@ -84,6 +84,40 @@ CFrameScheduler::Client * CFrameScheduler::FindClient(uint32_t clientID)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFrameScheduler::Client * CFrameScheduler::FindOrAllocateClient(
|
||||||
|
uint32_t clientID)
|
||||||
|
{
|
||||||
|
Client * client = FindClient(clientID);
|
||||||
|
if (client || !clientID)
|
||||||
|
return client;
|
||||||
|
|
||||||
|
Client * replacement = nullptr;
|
||||||
|
for (Client& candidate : m_clients)
|
||||||
|
{
|
||||||
|
if (!candidate.clientID)
|
||||||
|
{
|
||||||
|
replacement = &candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A schedule can arrive before its frame subscriptions are visible.
|
||||||
|
// Such provisional entries must not prevent a real subscriber from
|
||||||
|
// obtaining one of the bounded scheduler slots.
|
||||||
|
if (candidate.subscribed || candidate.subscriptionSeen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!replacement || candidate.expiry < replacement->expiry)
|
||||||
|
replacement = &candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replacement)
|
||||||
|
{
|
||||||
|
*replacement = {};
|
||||||
|
replacement->clientID = clientID;
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
CFrameScheduler::Publication * CFrameScheduler::FindPublication(
|
CFrameScheduler::Publication * CFrameScheduler::FindPublication(
|
||||||
const Schedule& schedule, uint32_t frameSerial)
|
const Schedule& schedule, uint32_t frameSerial)
|
||||||
{
|
{
|
||||||
@@ -272,15 +306,7 @@ void CFrameScheduler::UpdateSubscribers(const uint32_t * clientIDs,
|
|||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i)
|
for (unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
Client * client = FindClient(clientIDs[i]);
|
Client * client = FindOrAllocateClient(clientIDs[i]);
|
||||||
if (!client)
|
|
||||||
for (Client& candidate : m_clients)
|
|
||||||
if (!candidate.clientID)
|
|
||||||
{
|
|
||||||
candidate.clientID = clientIDs[i];
|
|
||||||
client = &candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
@@ -362,15 +388,7 @@ bool CFrameScheduler::UpdateSchedule(uint32_t sourceClientID,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&m_lock);
|
AcquireSRWLockExclusive(&m_lock);
|
||||||
Client * client = FindClient(schedule.clientID);
|
Client * client = FindOrAllocateClient(schedule.clientID);
|
||||||
if (!client)
|
|
||||||
for (Client& candidate : m_clients)
|
|
||||||
if (!candidate.clientID)
|
|
||||||
{
|
|
||||||
candidate.clientID = schedule.clientID;
|
|
||||||
client = &candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!client)
|
if (!client)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ private:
|
|||||||
uint64_t m_lastLogPublished = 0;
|
uint64_t m_lastLogPublished = 0;
|
||||||
|
|
||||||
Client * FindClient(uint32_t clientID);
|
Client * FindClient(uint32_t clientID);
|
||||||
|
Client * FindOrAllocateClient(uint32_t clientID);
|
||||||
Publication * FindPublication(const Schedule& schedule,
|
Publication * FindPublication(const Schedule& schedule,
|
||||||
uint32_t frameSerial);
|
uint32_t frameSerial);
|
||||||
bool ElectOwner(uint64_t now, uint32_t resetClientID = 0);
|
bool ElectOwner(uint64_t now, uint32_t resetClientID = 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user