summaryrefslogtreecommitdiff
path: root/indra/llmessage/llcircuit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llcircuit.cpp')
-rw-r--r--indra/llmessage/llcircuit.cpp109
1 files changed, 58 insertions, 51 deletions
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 0db9f8e2f1..3ba2dfb104 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -2,30 +2,25 @@
* @file llcircuit.cpp
* @brief Class to track UDP endpoints for the message system.
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -60,8 +55,8 @@
#include "llrand.h"
#include "llstl.h"
#include "lltransfermanager.h"
+#include "llmodularmath.h"
-const F32 PING_INTERVAL = 5.f; // seconds
const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked.
const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked.
@@ -69,12 +64,15 @@ const F32 TARGET_PERIOD_LENGTH = 5.f; // seconds
const F32 LL_DUPLICATE_SUPPRESSION_TIMEOUT = 60.f; //seconds - this can be long, as time-based cleanup is
// only done when wrapping packetids, now...
-LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id)
+LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
+ const F32 circuit_heartbeat_interval, const F32 circuit_timeout)
: mHost (host),
mWrapID(0),
mPacketsOutID(0),
mPacketsInID(in_id),
mHighestPacketID(in_id),
+ mTimeoutCallback(NULL),
+ mTimeoutUserData(NULL),
mTrusted(FALSE),
mbAllowTimeout(TRUE),
mbAlive(TRUE),
@@ -100,11 +98,14 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id)
mBytesOutLastPeriod(0),
mBytesInThisPeriod(0),
mBytesOutThisPeriod(0),
- mPeakBPSIn(0),
- mPeakBPSOut(0),
+ mPeakBPSIn(0.f),
+ mPeakBPSOut(0.f),
mPeriodTime(0.0),
mExistenceTimer(),
- mCurrentResendCount(0)
+ mCurrentResendCount(0),
+ mLastPacketGap(0),
+ mHeartbeatInterval(circuit_heartbeat_interval),
+ mHeartbeatTimeout(circuit_timeout)
{
// Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
// running a message system loop.
@@ -112,14 +113,11 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id)
F32 distribution_offset = ll_frand();
mPingTime = mt_sec;
- mLastPingSendTime = mt_sec + PING_INTERVAL * distribution_offset;
+ mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset;
mLastPingReceivedTime = mt_sec;
- mNextPingSendTime = mLastPingSendTime + 0.95*PING_INTERVAL + ll_frand(0.1f*PING_INTERVAL);
+ mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
mPeriodTime = mt_sec;
- mTimeoutCallback = NULL;
- mTimeoutUserData = NULL;
-
mLocalEndPointID.generate();
}
@@ -184,7 +182,7 @@ LLCircuitData::~LLCircuitData()
std::ostream_iterator<TPACKETID> append(str, " ");
str << "MSG: -> " << mHost << "\tABORTING RELIABLE:\t";
std::copy(doomed.begin(), doomed.end(), append);
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
}
@@ -204,7 +202,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
std::ostringstream str;
str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
<< packetp->mPacketID;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
if (packetp->mCallback)
{
@@ -238,7 +236,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
std::ostringstream str;
str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
<< packetp->mPacketID;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
if (packetp->mCallback)
{
@@ -342,7 +340,7 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now)
std::ostringstream str;
str << "MSG: -> " << packetp->mHost
<< "\tRESENDING RELIABLE:\t" << packetp->mPacketID;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
packetp->mBuffer[0] |= LL_RESENT_FLAG; // tag packet id as being a resend
@@ -403,7 +401,7 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now)
std::ostringstream str;
str << "MSG: -> " << packetp->mHost << "\tABORTING RELIABLE:\t"
<< packetp->mPacketID;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
if (packetp->mCallback)
@@ -428,7 +426,8 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now)
}
-LLCircuit::LLCircuit() : mLastCircuit(NULL)
+LLCircuit::LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : mLastCircuit(NULL),
+ mHeartbeatInterval(circuit_heartbeat_interval), mHeartbeatTimeout(circuit_timeout)
{
}
@@ -446,7 +445,7 @@ LLCircuitData *LLCircuit::addCircuitData(const LLHost &host, TPACKETID in_id)
{
// This should really validate if one already exists
llinfos << "LLCircuit::addCircuitData for " << host << llendl;
- LLCircuitData *tempp = new LLCircuitData(host, in_id);
+ LLCircuitData *tempp = new LLCircuitData(host, in_id, mHeartbeatInterval, mHeartbeatTimeout);
mCircuitData.insert(circuit_data_map::value_type(host, tempp));
mPingSet.insert(tempp);
@@ -676,6 +675,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
mPacketsIn++;
setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
+ mLastPacketGap = 0;
+ mOutOfOrderRate.count(0);
return;
}
@@ -683,6 +684,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
// now, check to see if we've got a gap
+ U32 gap = 0;
if ((mPacketsInID == id))
{
// nope! bump and wrap the counter, then return
@@ -704,13 +706,18 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
// otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map
// and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID
+ // babbage: all operands in expression are unsigned, so modular
+ // arithmetic will always find correct gap, regardless of wrap arounds.
+ const U8 width = 24;
+ gap = LLModularMath::subtract<width>(mPacketsInID, id);
+
if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end())
{
if(gMessageSystem->mVerboseLog)
{
std::ostringstream str;
str << "MSG: <- " << mHost << "\tRECOVERING LOST:\t" << id;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
// llinfos << "removing potential lost: " << id << llendl;
mPotentialLostPackets.erase(id);
@@ -729,7 +736,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
std::ostringstream str;
str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
<< index;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
// llinfos << "adding potential lost: " << index << llendl;
@@ -747,7 +754,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
std::ostringstream str;
str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
<< id << " expected " << index;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
}
@@ -765,6 +772,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
}
}
+ mOutOfOrderRate.count(gap);
+ mLastPacketGap = gap;
}
@@ -790,7 +799,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
// Always remember to remove it from the set before changing the sorting
// key (mNextPingSendTime)
mPingSet.erase(psit);
- cdp->mNextPingSendTime = cur_time + PING_INTERVAL;
+ cdp->mNextPingSendTime = cur_time + mHeartbeatInterval;
mPingSet.insert(cdp);
continue;
}
@@ -808,7 +817,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
if (cdp->updateWatchDogTimers(msgsys))
{
// Randomize our pings a bit by doing some up to 5% early or late
- F64 dt = 0.95f*PING_INTERVAL + ll_frand(0.1f*PING_INTERVAL);
+ F64 dt = 0.95f*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
// Remove it, and reinsert it with the new next ping time.
// Always remove before changing the sorting key.
@@ -969,7 +978,7 @@ BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
std::ostringstream str;
str << "MSG: <- " << mHost << "\tLOST PACKET:\t"
<< (*it).first;
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
mPotentialLostPackets.erase(it++);
}
@@ -1036,7 +1045,7 @@ BOOL LLCircuitData::checkCircuitTimeout()
F64 time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
// Nota Bene: This needs to be turned off if you are debugging multiple simulators
- if (time_since_last_ping > PING_INTERVAL_MAX)
+ if (time_since_last_ping > mHeartbeatTimeout)
{
llwarns << "LLCircuitData::checkCircuitTimeout for " << mHost << " last ping " << time_since_last_ping << " seconds ago." <<llendl;
setAlive(FALSE);
@@ -1052,10 +1061,7 @@ BOOL LLCircuitData::checkCircuitTimeout()
return FALSE;
}
}
- else if (time_since_last_ping > PING_INTERVAL_ALARM)
- {
- //llwarns << "Unresponsive circuit: " << mHost << ": " << time_since_last_ping << " seconds since last ping."<< llendl;
- }
+
return TRUE;
}
@@ -1114,7 +1120,7 @@ void LLCircuit::sendAcks()
str << "MSG: -> " << cd->mHost << "\tPACKET ACKS:\t";
std::ostream_iterator<TPACKETID> append(str, " ");
std::copy(cd->mAcks.begin(), cd->mAcks.end(), append);
- llinfos << str.str().c_str() << llendl;
+ llinfos << str.str() << llendl;
}
// empty out the acks list
@@ -1269,7 +1275,7 @@ void LLCircuitData::pingTimerStop(const U8 ping_id)
delta_ping += 256;
}
- U32 msec = (U32) ((delta_ping*PING_INTERVAL + time) * 1000.f);
+ U32 msec = (U32) ((delta_ping*mHeartbeatInterval + time) * 1000.f);
setPingDelay(msec);
mPingsInTransit = delta_ping;
@@ -1360,7 +1366,8 @@ F32 LLCircuitData::getPingInTransitTime()
if (mPingsInTransit)
{
- time_since_ping_was_sent = (F32)((mPingsInTransit*PING_INTERVAL - 1) + (LLMessageSystem::getMessageTimeSeconds() - mPingTime))*1000.f;
+ time_since_ping_was_sent = (F32)((mPingsInTransit*mHeartbeatInterval - 1)
+ + (LLMessageSystem::getMessageTimeSeconds() - mPingTime))*1000.f;
}
return time_since_ping_was_sent;