// this method is called during the message system processAcks() to // send out any acks that did not get sent already. void LLCircuit::sendAcks(F32 collect_time) { collect_time = llclamp(collect_time, 0.f, LL_COLLECT_ACK_TIME_MAX); LLCircuitData* cd; circuit_data_map::iterator it = mSendAckMap.begin(); while (it != mSendAckMap.end()) { circuit_data_map::iterator cur_it = it++; cd = (*cur_it).second; S32 count = (S32)cd->mAcks.size(); F32 age = cd->getAgeInSeconds() - cd->mAckCreationTime; if (age > collect_time || count == 0) { if (count>0) { // send the packet acks S32 acks_this_packet = 0; for(S32 i = 0; i < count; ++i) { if(acks_this_packet == 0) { gMessageSystem->newMessageFast(_PREHASH_PacketAck); } gMessageSystem->nextBlockFast(_PREHASH_Packets); gMessageSystem->addU32Fast(_PREHASH_ID, cd->mAcks[i]); ++acks_this_packet; if(acks_this_packet > 250) { gMessageSystem->sendMessage(cd->mHost); acks_this_packet = 0; } } if(acks_this_packet > 0) { gMessageSystem->sendMessage(cd->mHost); } if(gMessageSystem->mVerboseLog) { std::ostringstream str; str << "MSG: -> " << cd->mHost << "\tPACKET ACKS:\t"; std::ostream_iterator<TPACKETID> append(str, " "); std::copy(cd->mAcks.begin(), cd->mAcks.end(), append); LL_INFOS() << str.str() << LL_ENDL; } // empty out the acks list cd->mAcks.clear(); cd->mAckCreationTime = 0.f; } // remove data map mSendAckMap.erase(cur_it); } } }
// static BOOL LLFloaterMessageLog::onClickCloseCircuit(void* user_data) { LLNetListItem* itemp = (LLNetListItem*)user_data; LLCircuitData* cdp = (LLCircuitData*)itemp->mCircuitData; if(!cdp) return FALSE; LLHost myhost = cdp->getHost(); LLSD args; args["MESSAGE"] = "This will delete local circuit data.\nDo you want to tell the remote host to close the circuit too?"; LLSD payload; payload["circuittoclose"] = myhost.getString(); LLNotificationsUtil::add("GenericAlertYesCancel", args, payload, onConfirmCloseCircuit); return TRUE; }
U32 LLViewerRegion::getPacketsLost() const { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mHost); if (!cdp) { llinfos << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mHost << llendl; return 0; } else { return cdp->getPacketsLost(); } }
void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size) { F64 now = LLMessageSystem::getMessageTimeSeconds(); unacked_list_length = 0; unacked_list_size = 0; LLCircuitData* circ; circuit_data_map::iterator end = mUnackedCircuitMap.end(); for(circuit_data_map::iterator it = mUnackedCircuitMap.begin(); it != end; ++it) { circ = (*it).second; unacked_list_length += circ->resendUnackedPackets(now); unacked_list_size += circ->getUnackedPacketBytes(); } }
void LLWorld::printPacketsLost() { llinfos << "Simulators:" << llendl; llinfos << "----------" << llendl; LLCircuitData *cdp = NULL; for (region_list_t::iterator iter = mActiveRegionList.begin(); iter != mActiveRegionList.end(); ++iter) { LLViewerRegion* regionp = *iter; cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); if (cdp) { LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); llinfos << regionp->getHost() << ", range: " << range.length() << " packets lost: " << cdp->getPacketsLost() << llendl; } } }
// static bool LLFloaterMessageLog::onConfirmCloseCircuit(const LLSD& notification, const LLSD& response ) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLCircuitData* cdp = gMessageSystem->mCircuitInfo.findCircuit(LLHost(notification["payload"]["circuittoclose"].asString())); if(!cdp) return false; LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(cdp->getHost()); switch(option) { case 0: // yes gMessageSystem->newMessageFast(_PREHASH_CloseCircuit); gMessageSystem->sendReliable(cdp->getHost()); break; case 2: // cancel return false; break; case 1: // no default: break; } if(gMessageSystem->findCircuitCode(cdp->getHost())) gMessageSystem->disableCircuit(cdp->getHost()); else gMessageSystem->mCircuitInfo.removeCircuitData(cdp->getHost()); if(regionp) { LLHost myhost = regionp->getHost(); LLSD args; args["MESSAGE"] = "That host had a region associated with it.\nDo you want to clean that up?"; LLSD payload; payload["regionhost"] = myhost.getString(); LLNotificationsUtil::add("GenericAlertYesCancel", args, payload, onConfirmRemoveRegion); } return false; }
void LLViewerRegion::updateNetStats() { F32 dt = mLastNetUpdate.getElapsedTimeAndResetF32(); LLCircuitData *cdp = LLMessageSystem::getInstance()->mCircuitInfo.findCircuit( m_host ); if (!cdp) { mAlive = false; return; } mAlive = true; mDeltaTime = dt; mLastPacketsIn = mPacketsIn; mLastBitsIn = mBitsIn; mLastPacketsOut = mPacketsOut; mLastPacketsLost = mPacketsLost; mPacketsIn = cdp->getPacketsIn(); mBitsIn = 8 * cdp->getBytesIn(); mPacketsOut = cdp->getPacketsOut(); mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); mBitStat.addValue(mBitsIn - mLastBitsIn); mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); mPacketsLostStat.addValue(mPacketsLost); }
void update_statistics(U32 frame_count) { gTotalWorldBytes += gVLManager.getTotalBytes(); gTotalObjectBytes += gObjectBits / 8; // make sure we have a valid time delta for this frame if (gFrameIntervalSeconds > 0.f) { if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds); } else if (gAgent.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds); } else if (gFloaterTools && gFloaterTools->getVisible()) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds); } } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment")); #endif LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_FRAME)); F64 idle_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IDLE); F64 network_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_NETWORK); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IMAGE_UPDATE)); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_STATESORT )); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_RENDER_GEOMETRY)); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { LLViewerStats::getInstance()->mSimPingStat.addValue(cdp->getPingDelay()); gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); gSimPingCount++; } else { LLViewerStats::getInstance()->mSimPingStat.addValue(10000); } LLViewerStats::getInstance()->mFPSStat.addValue(1); F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f); LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f); LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) { gDebugTimers[0].pause(); } else { gDebugTimers[0].unpause(); } { static F32 visible_avatar_frames = 0.f; static F32 avg_visible_avatars = 0; F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars; if (visible_avatars > 0.f) { visible_avatar_frames = 1.f; avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames; } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars); } LLWorld::getInstance()->updateNetStats(); LLWorld::getInstance()->requestCacheMisses(); // Reset all of these values. gVLManager.resetBitCounts(); gObjectBits = 0; // gDecodedBits = 0; // Only update texture stats ones per second so that they are less noisy { static const F32 texture_stats_freq = 1.f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerImageList::sTextureBits/1024.f); LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerImageList::sTexturePackets); gTotalTextureBytes += LLViewerImageList::sTextureBits / 8; LLViewerImageList::sTextureBits = 0; LLViewerImageList::sTexturePackets = 0; texture_stats_timer.reset(); } } #if LL_LCD_COMPILE bool LCDenabled = gLcdScreen->Enabled(); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, LCDenabled); #else LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, false); #endif }
void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys) { F64 cur_time = LLMessageSystem::getMessageTimeSeconds(); S32 count = mPingSet.size(); S32 cur = 0; // Only process each circuit once at most, stop processing if no circuits while((cur < count) && !mPingSet.empty()) { cur++; LLCircuit::ping_set_t::iterator psit = mPingSet.begin(); LLCircuitData *cdp = *psit; if (!cdp->mbAlive) { // We suspect that this case should never happen, given how // the alive status is set. // Skip over dead circuits, just add the ping interval and push it to the back // Always remember to remove it from the set before changing the sorting // key (mNextPingSendTime) mPingSet.erase(psit); cdp->mNextPingSendTime = cur_time + PING_INTERVAL; mPingSet.insert(cdp); continue; } else { // Check to see if this needs a ping if (cur_time < cdp->mNextPingSendTime) { // This circuit doesn't need a ping, break out because // we have a sorted list, thus no more circuits need pings break; } // Update watchdog timers 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); // Remove it, and reinsert it with the new next ping time. // Always remove before changing the sorting key. mPingSet.erase(psit); cdp->mNextPingSendTime = cur_time + dt; mPingSet.insert(cdp); // Update our throttles cdp->mThrottles.dynamicAdjust(); // Update some stats, this is not terribly important cdp->checkPeriodTime(); } else { // This mPingSet.erase isn't necessary, because removing the circuit will // remove the ping set. //mPingSet.erase(psit); removeCircuitData(cdp->mHost); } } } }
void LLFloaterMessageLog::refreshNetInfo(BOOL force) { if(mNetInfoMode != NI_NET) return; LLScrollListCtrl* scrollp = getChild<LLScrollListCtrl>("net_list"); LLScrollListItem* selected_itemp = scrollp->getFirstSelected(); if(selected_itemp) { if(!force) if(getChild<LLTextEditor>("net_info")->hasSelection()) return; LLNetListItem* itemp = findNetListItem(selected_itemp->getUUID()); if(itemp) { std::string info(llformat("%s\n--------------------------------\n\n", itemp->mName.c_str())); if(itemp->mCircuitData) { LLCircuitData* cdp = itemp->mCircuitData; info.append("Circuit\n--------------------------------\n"); info.append(llformat(" * Host: %s\n", cdp->getHost().getString().c_str())); S32 seconds = (S32)cdp->getAgeInSeconds(); S32 minutes = seconds / 60; seconds = seconds % 60; S32 hours = minutes / 60; minutes = minutes % 60; info.append(llformat(" * Age: %dh %dm %ds\n", hours, minutes, seconds)); info.append(llformat(" * Alive: %s\n", cdp->isAlive() ? "yes" : "no")); info.append(llformat(" * Blocked: %s\n", cdp->isBlocked() ? "yes" : "no")); info.append(llformat(" * Allow timeout: %s\n", cdp->getAllowTimeout() ? "yes" : "no")); info.append(llformat(" * Trusted: %s\n", cdp->getTrusted() ? "yes" : "no")); info.append(llformat(" * Ping delay: %d\n", cdp->getPingDelay())); info.append(llformat(" * Packets out: %d\n", cdp->getPacketsOut())); info.append(llformat(" * Bytes out: %d\n", cdp->getBytesOut())); info.append(llformat(" * Packets in: %d\n", cdp->getPacketsIn())); info.append(llformat(" * Bytes in: %d\n", cdp->getBytesIn())); info.append(llformat(" * Endpoint ID: %s\n", cdp->getLocalEndPointID().asString().c_str())); info.append(llformat(" * Remote ID: %s\n", cdp->getRemoteID().asString().c_str())); info.append(llformat(" * Remote session ID: %s\n", cdp->getRemoteSessionID().asString().c_str())); } childSetText("net_info", info); } else childSetText("net_info", std::string("")); } else childSetText("net_info", std::string("")); }
void update_statistics() { gTotalWorldBytes += gVLManager.getTotalBytes(); gTotalObjectBytes += gObjectBits / 8; LLViewerStats& stats = LLViewerStats::instance(); // make sure we have a valid time delta for this frame if (gFrameIntervalSeconds > 0.f) { if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds); } else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds); } else if (gFloaterTools && gFloaterTools->getVisible()) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds); } } stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment")); #endif stats.setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame")); F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle"); F64 network_secs = gDebugView->mFastTimerView->getTime("Network"); stats.setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); stats.setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); stats.setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); stats.setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); stats.setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry")); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { stats.mSimPingStat.addValue(cdp->getPingDelay()); gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); gSimPingCount++; } else { stats.mSimPingStat.addValue(10000); } stats.mFPSStat.addValue(1); F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); stats.mLayersKBitStat.addValue(layer_bits/1024.f); stats.mObjectKBitStat.addValue(gObjectBits/1024.f); stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) { gTextureTimer.pause(); } else { gTextureTimer.unpause(); } { static F32 visible_avatar_frames = 0.f; static F32 avg_visible_avatars = 0; F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars; if (visible_avatars > 0.f) { visible_avatar_frames = 1.f; avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames; } stats.setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars); } LLWorld::getInstance()->updateNetStats(); LLWorld::getInstance()->requestCacheMisses(); // Reset all of these values. gVLManager.resetBitCounts(); gObjectBits = 0; // gDecodedBits = 0; // Only update texture stats periodically so that they are less noisy { static const F32 texture_stats_freq = 0.25f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f); stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; LLViewerTextureList::sTextureBits = 0; LLViewerTextureList::sTexturePackets = 0; texture_stats_timer.reset(); } } { static const F32 mem_stats_freq = 10.f; static LLFrameTimer mem_stats_timer; if (mem_stats_timer.getElapsedTimeF32() >= mem_stats_freq) { stats.mMallocStat.addValue(SGMemStat::getMalloc()/1024.f/1024.f); mem_stats_timer.reset(); } } }
void LLTransferSourceChannel::updateTransfers() { // Actually, this should do the following: // Decide if we can actually send data. // If so, update priorities so we know who gets to send it. // Send data from the sources, while updating until we've sent our throttle allocation. LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(getHost()); if (!cdp) { return; } if (cdp->isBlocked()) { // *NOTE: We need to make sure that the throttle bits // available gets reset. // We DON'T want to send any packets if they're blocked, they'll just end up // piling up on the other end. //llwarns << "Blocking transfers due to blocked circuit for " << getHost() << llendl; return; } const S32 throttle_id = mThrottleID; LLThrottleGroup &tg = cdp->getThrottleGroup(); if (tg.checkOverflow(throttle_id, 0.f)) { return; } LLPriQueueMap<LLTransferSource *>::pqm_iter iter, next; BOOL done = FALSE; for (iter = mTransferSources.mMap.begin(); (iter != mTransferSources.mMap.end()) && !done;) { //llinfos << "LLTransferSourceChannel::updateTransfers()" << llendl; // Do stuff. next = iter; next++; LLTransferSource *tsp = iter->second; U8 *datap = NULL; S32 data_size = 0; BOOL delete_data = FALSE; S32 packet_id = 0; S32 sent_bytes = 0; LLTSCode status = LLTS_OK; // Get the packetID for the next packet that we're transferring. packet_id = tsp->getNextPacketID(); status = tsp->dataCallback(packet_id, DEFAULT_PACKET_SIZE, &datap, data_size, delete_data); if (status == LLTS_SKIP) { // We don't have any data, but we're not done, just go on. // This will presumably be used for streaming or async transfers that // are stalled waiting for data from another source. iter=next; continue; } LLUUID *cb_uuid = new LLUUID(tsp->getID()); LLUUID transaction_id = tsp->getID(); // Send the data now, even if it's an error. // The status code will tell the other end what to do. gMessageSystem->newMessage("TransferPacket"); gMessageSystem->nextBlock("TransferData"); gMessageSystem->addUUID("TransferID", tsp->getID()); gMessageSystem->addS32("ChannelType", getChannelType()); gMessageSystem->addS32("Packet", packet_id); // HACK! Need to put in a REAL packet id gMessageSystem->addS32("Status", status); gMessageSystem->addBinaryData("Data", datap, data_size); sent_bytes = gMessageSystem->getCurrentSendTotal(); gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, 0.f, LLTransferManager::reliablePacketCallback, (void**)cb_uuid); // Do bookkeeping for the throttle done = tg.throttleOverflow(throttle_id, sent_bytes*8.f); gTransferManager.addTransferBitsOut(mChannelType, sent_bytes*8); // Clean up our temporary data. if (delete_data) { delete[] datap; datap = NULL; } if (findTransferSource(transaction_id) == NULL) { //Warning! In the case of an aborted transfer, the sendReliable call above calls //AbortTransfer which in turn calls deleteTransfer which means that somewhere way //down the chain our current iter can get invalidated resulting in an infrequent //sim crash. This check gets us to a valid transfer source in this event. iter=next; continue; } // Update the packet counter tsp->setLastPacketID(packet_id); switch (status) { case LLTS_OK: // We're OK, don't need to do anything. Keep sending data. break; case LLTS_ERROR: llwarns << "Error in transfer dataCallback!" << llendl; // fall through case LLTS_DONE: // We need to clean up this transfer source. //llinfos << "LLTransferSourceChannel::updateTransfers() " << tsp->getID() << " done" << llendl; tsp->completionCallback(status); delete tsp; mTransferSources.mMap.erase(iter); iter = next; break; default: llerrs << "Unknown transfer error code!" << llendl; } // At this point, we should do priority adjustment (since some transfers like // streaming transfers will adjust priority based on how much they've sent and time, // but I'm not going to bother yet. - djs. } }