这里接着上一次获取纹理图片线程,继续分析发送纹理图片请求到服务器。代码如下:
#001 void LLTextureFetch::sendRequestListToSimulators()
#002 {
#003
const S32 IMAGES_PER_REQUEST = 50;
#004
const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp
#005
const F32 MIN_REQUEST_TIME = 1.0f;
#006
const F32 MIN_DELTA_PRIORITY = 1000.f;
#007
先同步多线程的访问。
#008
LLMutexLock lock(&mQueueMutex);
#009
#010
// Send requests
#011
typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
#012
typedef std::map< LLHost, request_list_t > work_request_map_t;
#013
work_request_map_t requests;
下面循环地分析已经放到请求队列里的下载请求。
#014
for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); )
#015
{
#016
queue_t::iterator curiter = iter++;
下面获取请求的工作对象。
#017
LLTextureFetchWorker* req = getWorker(*curiter);
#018
if (!req)
#019
{
#020
mNetworkQueue.erase(curiter);
#021
continue; // paranoia
#022
}
#023
if (req->mID == mDebugID)
#024
{
#025
mDebugCount++; // for setting breakpoints
#026
}
检查是否已经下载所有数据。
#027
if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1)
#028
{
#029
// We have all the packets... make sure this is high priority
#030 //
req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority);
#031
continue;
#032
}
#033
F32 elapsed = req->mRequestedTimer.getElapsedTimeF32();
#034
F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority);
按优先级和请求到达的时间来分类放到请求下载队列。
#035
if ((req->mSimRequestedDiscard != req->mDesiredDiscard) ||
#036
(delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) ||
#037
(elapsed >= LAZY_FLUSH_TIMEOUT))
#038
{
#039
requests[req->mHost].insert(req);
#040
}
#041
}
#042
#043
std::string http_url;
#044 #if 0
#045
if (gSavedSettings.getBOOL("ImagePipelineUseHTTP"))
#046
{
#047
LLViewerRegion* region = gAgent.getRegion();
#048
if (region)
#049
{
#050
http_url = region->getCapability("RequestTextureDownload");
#051
}
#052
}
#053 #endif
#054
下面开始循环地发送纹理图片请求到服务器。
#055
for (work_request_map_t::iterator iter1 = requests.begin();
#056
iter1 != requests.end(); ++iter1)
#057
{
#058
bool use_http = http_url.empty() ? false : true;
#059
LLHost host = iter1->first;
#060
// invalid host = use agent host
#061
if (host == LLHost::invalid)
#062
{
#063
host = gAgent.getRegionHost();
#064
}
#065
else
#066
{
#067
use_http = false;
#068
}
#069
#070
if (use_http)
#071
{
#072
}
#073
else
#074
{
通过消息系统向服务器发送请求。
#075
S32 request_count = 0;
#076
for (request_list_t::iterator iter2 = iter1->second.begin();
#077
iter2 != iter1->second.end(); ++iter2)
#078
{
取得请求对象。
#079
LLTextureFetchWorker* req = *iter2;
#080
req->mSentRequest = LLTextureFetchWorker::SENT_SIM;
创建一个新的消息来发送请求。
#081
if (0 == request_count)
#082
{
#083
gMessageSystem->newMessageFast(_PREHASH_RequestImage);
#084
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
#085
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
#086
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
#087
}
#088
S32 packet = req->mLastPacket + 1;
下面开始创始消息新块数据。
#089
gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
添加图片ID到消息里。
#090
gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
#091
gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard);
#092
gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority);
#093
gMessageSystem->addU32Fast(_PREHASH_Packet, packet);
#094
gMessageSystem->addU8Fast(_PREHASH_Type, req->mType);
#095 //
llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard
#096 //
<< " Packet: " << packet << " Priority: " << req->mImagePriority << llendl;
#097
#098
req->lockWorkData();
#099
req->mSimRequestedDiscard = req->mDesiredDiscard;
#100
req->mRequestedPriority = req->mImagePriority;
#101
req->mRequestedTimer.reset();
#102
req->unlockWorkData();
#103
request_count++;
#104
if (request_count >= IMAGES_PER_REQUEST)
#105
{
#106 //
llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
#107
gMessageSystem->sendSemiReliable(host, NULL, NULL);
#108
request_count = 0;
#109
}
#110
}
#111
if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
#112
{
#113 //
llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl;
通过消息系统发送纹理请求下载到服务器。
#114
gMessageSystem->sendSemiReliable(host, NULL, NULL);
#115
request_count = 0;
#116
}
#117
}
#118
}
#119
发送一些取消下载的纹理图片。
#120
// Send cancelations
#121
if (!mCancelQueue.empty())
#122
{
#123
for (cancel_queue_t::iterator iter1 = mCancelQueue.begin();
#124
iter1 != mCancelQueue.end(); ++iter1)
#125
{
#126
LLHost host = iter1->first;
#127
if (host == LLHost::invalid)
#128
{
#129
host = gAgent.getRegionHost();
#130
}
#131
S32 request_count = 0;
#132
for (queue_t::iterator iter2 = iter1->second.begin();
#133
iter2 != iter1->second.end(); ++iter2)
#134
{
#135
if (0 == request_count)
#136
{
#137
gMessageSystem->newMessageFast(_PREHASH_RequestImage);
#138
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
#139
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
#140
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
#141
}
#142
gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
#143
gMessageSystem->addUUIDFast(_PREHASH_Image, *iter2);
#144
gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, -1);
#145
gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, 0);
#146
gMessageSystem->addU32Fast(_PREHASH_Packet, 0);
#147
gMessageSystem->addU8Fast(_PREHASH_Type, 0);
#148 //
llinfos << "CANCELING IMAGE REQUEST: " << (*iter2) << llendl;
#149
#150
request_count++;
#151
if (request_count >= IMAGES_PER_REQUEST)
#152
{
#153
gMessageSystem->sendSemiReliable(host, NULL, NULL);
#154
request_count = 0;
#155
}
#156
}
#157
if (request_count > 0 && request_count < IMAGES_PER_REQUEST)
#158
{
#159
gMessageSystem->sendSemiReliable(host, NULL, NULL);
#160
}
#161
}
#162
mCancelQueue.clear();
#163
}
#164 }
通过上面的代码,就可以清晰地看到怎么样把纹理的图片请求发送到服务器的,它是先把请求分类,主要按请求的时间和优先级来决定的。接着把这些需要下载的请求组成一个消息包,通过网络消息系统向服务器发送出去。在这里还处理了那些需要取消下载的纹理请求,由于下载比较大的纹理图片是非常耗费时间和带宽的,应该添加取消下载的功能,这是一个比较好的设计。
//蔡军生 2008/4/27 QQ:9073204 深圳