Browse Source

Refactor Pending Loads

Adam Johnson 12 years ago
parent
commit
e953c0c542
  1. 128
      Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp
  2. 6
      Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h

128
Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.cpp

@ -559,94 +559,64 @@ int plNetClientMgr::Update(double secs)
// //
void plNetClientMgr::ICheckPendingStateLoad(double secs) void plNetClientMgr::ICheckPendingStateLoad(double secs)
{ {
if ((!fPendingLoads.empty() && GetFlagsBit(kPlayingGame)) || (GetFlagsBit(kLoadingInitialAgeState) && !GetFlagsBit(kNeedInitialAgeStateCount))) // We only care if we're in an age or loading state
if (!(GetFlagsBit(kPlayingGame) || (GetFlagsBit(kLoadingInitialAgeState) && !GetFlagsBit(kNeedInitialAgeStateCount))))
return;
for (auto it = fPendingLoads.begin(); it != fPendingLoads.end();)
{ {
PendingLoadsList::iterator it = fPendingLoads.begin(); PendingLoad* load = *it;
while ( it!=fPendingLoads.end() )
// If no key has been cached, we need to find it.
if (!load->fKey)
{ {
PendingLoad * pl = (*it); load->fKey = hsgResMgr::ResMgr()->FindKey(load->fUoid);
// cache rcvr key // By this point, we should have all the age's keys downloaded from filesrv
if (!pl->fKey) // So, if fKey is null at this point, this state is garbage
if (!load->fKey)
{ {
// check for existence of key in dataset, excluding clone info. ErrorMsg("Key `%s` not found. Discarding state for `%s`",
plUoid tmpUoid = pl->fUoid; load->fUoid.GetObjectName().c_str(),
tmpUoid.SetClone(0,0); load->fSDRec->GetDescriptor()->GetName().c_str());
if ( !hsgResMgr::ResMgr()->FindKey( tmpUoid ) ) it = fPendingLoads.erase(it);
{ delete load;
// discard the state if object not found in dataset. continue;
hsLogEntry( DebugMsg( "Failed to find object %s in dataset. Discarding pending state '%s'",
tmpUoid.StringIze().c_str(),
pl->fSDRec->GetDescriptor()->GetName().c_str() ) );
delete pl;
it = fPendingLoads.erase(it);
continue;
}
// find and cache the real key.
pl->fKey = hsgResMgr::ResMgr()->FindKey(pl->fUoid);
} }
}
// deliver state if possible // Time to deliver the state!
plSynchedObject*so = pl->fKey ? plSynchedObject::ConvertNoRef(pl->fKey->ObjectIsLoaded()) : nil; plSynchedObject* synchObj = plSynchedObject::ConvertNoRef(load->fKey->ObjectIsLoaded());
if (so && so->IsFinal()) if (synchObj && synchObj->IsFinal())
{ {
plSDLModifierMsg* sdlMsg = new plSDLModifierMsg(pl->fSDRec->GetDescriptor()->GetName(), plSDLModifierMsg* msg = new plSDLModifierMsg(load->fSDRec->GetDescriptor()->GetName(), plSDLModifierMsg::kRecv);
plSDLModifierMsg::kRecv); msg->SetState(load->fSDRec, true);
sdlMsg->SetState( pl->fSDRec, true/*delete pl->fSDRec for us*/ ); load->fSDRec = nullptr;
sdlMsg->SetPlayerID( pl->fPlayerID ); msg->SetPlayerID(load->fPlayerID);
#ifdef HS_DEBUGGING #ifdef HS_DEBUGGING
if (plNetObjectDebugger::GetInstance()->IsDebugObject(so)) if (plNetObjectDebugger::GetInstance()->IsDebugObject(synchObj))
{
hsLogEntry( DebugMsg( "Delivering SDL state %s:%s", pl->fKey->GetName().c_str(),
pl->fSDRec->GetDescriptor()->GetName().c_str() ) );
// hsLogEntry(plNetObjectDebugger::GetInstance()->LogMsg(plString::Format("Dispatching SDL state, type %s to object:%s, locallyOwned=%d, st=%.3f rt=%.3f",
// pl->fSDRec->GetDescriptor()->GetName().c_str(), pl->fKey->GetName().c_str(),
// so->IsLocallyOwned()==plSynchedObject::kYes, secs, hsTimer::GetSeconds()).c_str()));
// hsLogEntry( pl->fSDRec->DumpToObjectDebugger( "Delivering SDL state", false, 0 ) );
}
#endif
sdlMsg->Send(pl->fKey);
pl->fSDRec = nil; // so it won't be deleted in the PendingLoad dtor.
delete pl;
it = fPendingLoads.erase(it);
}
else
{ {
// report old pending state DebugMsg("Delivering SDL State '%s' to %s owned key %s",
double rawSecs = hsTimer::GetSeconds(); msg->GetState()->GetDescriptor()->GetName().c_str(),
if ((rawSecs - pl->fQueuedTime) > 60.f /*secs*/) (synchObj->IsLocallyOwned() == plSynchedObject::kYes) ? "locally" : "remote",
{ load->fUoid.StringIze().c_str());
if (pl->fQueueTimeResets >= 5)
{
// if this is our fifth time in here then we've been queued
// for around 5 minutes and its time to go
WarningMsg( "Pending state '%s' for object [uoid:%s,key:%s] has been queued for about %f secs. Removing...",
pl->fSDRec && pl->fSDRec->GetDescriptor() ? pl->fSDRec->GetDescriptor()->GetName().c_str() : "?",
pl->fUoid.StringIze().c_str(), pl->fKey ? pl->fKey->GetUoid().StringIze().c_str() : "?",
( rawSecs - pl->fQueuedTime ) * pl->fQueueTimeResets);
delete pl;
it = fPendingLoads.erase(it);
continue;
}
WarningMsg( "Pending state '%s' for object [uoid:%s,key:%s] has been queued for about %f secs. %s",
pl->fSDRec && pl->fSDRec->GetDescriptor() ? pl->fSDRec->GetDescriptor()->GetName().c_str() : "?",
pl->fUoid.StringIze().c_str(), pl->fKey ? pl->fKey->GetUoid().StringIze().c_str() : "?",
( rawSecs - pl->fQueuedTime ) * pl->fQueueTimeResets,
so ? "(not loaded)" : "(not final)" );
// reset queue time so we don't spew too many log msgs.
pl->fQueuedTime = rawSecs;
pl->fQueueTimeResets += 1;
}
it++;
} }
#endif
msg->Send(load->fKey);
it = fPendingLoads.erase(it);
delete load;
}
else if (GetFlagsBit(kPlayingGame))
{
// If we're playing the game and object isn't loaded/final, then this state is probably
// never going to be useful (it's from some paged in hack or something that's been deleted)
// Throw it away.
it = fPendingLoads.erase(it);
delete load;
} }
else
++it;
} }
} }
@ -1437,11 +1407,10 @@ plUoid plNetClientMgr::GetAgeSDLObjectUoid(const char* ageName) const
// //
void plNetClientMgr::AddPendingLoad(PendingLoad *pl) void plNetClientMgr::AddPendingLoad(PendingLoad *pl)
{ {
pl->fQueuedTime = hsTimer::GetSeconds(); // timestamp
// find corresponding key // find corresponding key
pl->fKey = hsgResMgr::ResMgr()->FindKey(pl->fUoid); pl->fKey = hsgResMgr::ResMgr()->FindKey(pl->fUoid);
#ifdef HS_DEBUGGING
// check for age SDL state // check for age SDL state
if (!pl->fUoid.GetObjectName().IsNull() && !pl->fUoid.GetObjectName().Compare(plSDL::kAgeSDLObjectName)) if (!pl->fUoid.GetObjectName().IsNull() && !pl->fUoid.GetObjectName().Compare(plSDL::kAgeSDLObjectName))
{ {
@ -1451,6 +1420,7 @@ void plNetClientMgr::AddPendingLoad(PendingLoad *pl)
else else
DebugMsg("Found age hook object"); DebugMsg("Found age hook object");
} }
#endif
// check if object is ready // check if object is ready
if (pl->fKey) if (pl->fKey)

6
Sources/Plasma/PubUtilLib/plNetClient/plNetClientMgr.h

@ -124,14 +124,12 @@ public:
// must be set by user // must be set by user
plStateDataRecord* fSDRec; // the sdl data record plStateDataRecord* fSDRec; // the sdl data record
plUoid fUoid; // the object it's meant for plUoid fUoid; // the object it's meant for
uint32_t fPlayerID; // the player that originally sent the state uint32_t fPlayerID; // the player that originally sent the state
// set by NetClient // set by NetClient
plKey fKey; // the key of the object it's meant for plKey fKey; // the key of the object it's meant for
double fQueuedTime;
int fQueueTimeResets;
PendingLoad() : fSDRec(nil),fPlayerID(0),fKey(nil),fQueuedTime(0.0),fQueueTimeResets(0) {} PendingLoad() : fSDRec(nullptr), fPlayerID(0), fKey(nullptr) { }
~PendingLoad(); ~PendingLoad();
}; };

Loading…
Cancel
Save