#include #include "Platoon.h" #include "dprint.h" void Platoon::countStateChange(int user, robouser_t::state_t oldstate, robouser_t::state_t newstate) { (void)user; char buf1[256]; char buf2[256]; int i, pos; for (pos=i=0; i= robouser_t::UNINIT && oldstate < robouser_t::NUMSTATES); assert(newstate > robouser_t::UNINIT && newstate < robouser_t::NUMSTATES); if (oldstate != robouser_t::UNINIT) m_nInState[oldstate]--; m_nInState[newstate]++; for (pos=i=0; idelClient(r); /* just in case some event is pending */ r->shutDown(); m_users[r->getUser()] = NULL; delete r; DPRINT(("Platoon::reset: done deleting r\n")); } } m_sked->delClient(this); assert(m_sked->empty()); } /// Return the sum of m_nInState[first ... last] int Platoon::sumInState(robouser_t::state_t first, robouser_t::state_t last) { int i, num; for (num=0, i=first; i<=last; i++) num += m_nInState[i]; return num; } /*---------------------------------------------------------------------- Start another one of the robousers. getStatus() should be called periodically to check on their status. It's a good idea to wait until one connects before starting the next. ----------------------------------------------------------------------*/ int Platoon::startUser() { int i; int n; /* Find an empty slot; make a good guess at where next one is */ i = sumInState(robouser_t::CONNECT, robouser_t::GETTING); for (n=0; nstart(i); if (err) { DPRINT(("Platoon::startUser: init failed, err %d\n", err)); return err; } return 0; } /*---------------------------------------------------------------------- Reap any dead users. ----------------------------------------------------------------------*/ void Platoon::reap() { /* Reap all dead (= stopped) users */ while (! m_deadlist.empty()) { robouser_t *r = m_deadlist.front(); m_deadlist.pop_front(); DPRINT(("robouser%d::reap: RIP\n", r->getUser())); m_sked->delClient(r); /* just in case some event is pending */ r->shutDown(); m_users[r->getUser()] = NULL; delete r; DPRINT(("Platoon::reap: done deleting r\n")); } } /*---------------------------------------------------------------------- Call this periodically to check on status of the clients. *nconnecting = # of robousers still trying to connect *nalive = # of robousers who connected ok and are in good shape *ndead = # of robousers who have failed, and are out of action Returns total number of bytes transferred so far. ----------------------------------------------------------------------*/ long Platoon::getStatus(int *nconnecting, int *nalive, int *ndead) { reap(); if (nconnecting) *nconnecting = sumInState(robouser_t::CONNECT, m_lastConnectingState); if (nalive) *nalive = sumInState(robouser_t::CONNECT, robouser_t::GETTING); if (ndead) *ndead = sumInState(robouser_t::STOPPED, robouser_t::STOPPED); return m_bytesFetched; } /***************** Callback functions ************************************/ /*---------------------------------------------------------------------- When the time specified by addClient() has elapsed, Sked calls this method. ----------------------------------------------------------------------*/ void Platoon::skedCallback(clock_t now) { (void)now; while (sumInState(robouser_t::STOPPED, robouser_t::STOPPED) == 0 && sumInState(robouser_t::CONNECT, robouser_t::GETTING) < m_nuserTarget && sumInState(robouser_t::CONNECT, m_lastConnectingState) < m_nconnectingTarget) { // start another connection process DPRINT(("Platoon scb: connecting: %d/%d, alive: %d/%d, now %ld\n", sumInState(robouser_t::CONNECT, m_lastConnectingState), m_nconnectingTarget, sumInState(robouser_t::CONNECT, robouser_t::GETTING), m_nuserTarget, now)); int err = startUser(); if (err) { DPRINT(("Platoon::skedCallback: Error %d while trying to start a new user.\n", err)); return; } } }