00001
00032 #include "linden_common.h"
00033 #include "lllandmark.h"
00034
00035 #include <errno.h>
00036
00037 #include "message.h"
00038 #include "llregionhandle.h"
00039
00040 std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
00041 LLLandmark::region_map_t LLLandmark::mRegions;
00042 LLLandmark::region_callback_t LLLandmark::mRegionCallback;
00043
00044 LLLandmark::LLLandmark() :
00045 mGlobalPositionKnown(false)
00046 {
00047 }
00048
00049 LLLandmark::LLLandmark(const LLVector3d& pos) :
00050 mGlobalPositionKnown(true),
00051 mGlobalPos( pos )
00052 {
00053 }
00054
00055 bool LLLandmark::getGlobalPos(LLVector3d& pos)
00056 {
00057 if(mGlobalPositionKnown)
00058 {
00059 pos = mGlobalPos;
00060 }
00061 else if(mRegionID.notNull())
00062 {
00063 F32 g_x = -1.0;
00064 F32 g_y = -1.0;
00065 if(mRegionID == mLocalRegion.first)
00066 {
00067 from_region_handle(mLocalRegion.second, &g_x, &g_y);
00068 }
00069 else
00070 {
00071 region_map_t::iterator it = mRegions.find(mRegionID);
00072 if(it != mRegions.end())
00073 {
00074 from_region_handle((*it).second.mRegionHandle, &g_x, &g_y);
00075 }
00076 }
00077 if((g_x > 0.f) && (g_y > 0.f))
00078 {
00079 pos.mdV[0] = g_x + mRegionPos.mV[0];
00080 pos.mdV[1] = g_y + mRegionPos.mV[1];
00081 pos.mdV[2] = mRegionPos.mV[2];
00082 setGlobalPos(pos);
00083 }
00084 }
00085 return mGlobalPositionKnown;
00086 }
00087
00088 void LLLandmark::setGlobalPos(const LLVector3d& pos)
00089 {
00090 mGlobalPos = pos;
00091 mGlobalPositionKnown = true;
00092 }
00093
00094 bool LLLandmark::getRegionID(LLUUID& region_id)
00095 {
00096 if(mRegionID.notNull())
00097 {
00098 region_id = mRegionID;
00099 return true;
00100 }
00101 return false;
00102 }
00103
00104 LLVector3 LLLandmark::getRegionPos() const
00105 {
00106 return mRegionPos;
00107 }
00108
00109
00110
00111 LLLandmark* LLLandmark::constructFromString(const char *buffer)
00112 {
00113 const char* cur = buffer;
00114 S32 chars_read = 0;
00115 S32 count = 0;
00116 U32 version = 0;
00117
00118
00119 count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read );
00120 if(count != 1)
00121 {
00122 goto error;
00123 }
00124
00125 if(version == 1)
00126 {
00127 LLVector3d pos;
00128 cur += chars_read;
00129
00130 count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
00131 if( count != 3 )
00132 {
00133 goto error;
00134 }
00135 cur += chars_read;
00136
00137
00138 return new LLLandmark(pos);
00139 }
00140 else if(version == 2)
00141 {
00142
00143
00144 char region_id_str[MAX_STRING];
00145 LLVector3 pos;
00146 cur += chars_read;
00147 count = sscanf(
00148 cur,
00149 "region_id %254s\n%n",
00150 region_id_str, &chars_read);
00151 if(count != 1) goto error;
00152 cur += chars_read;
00153 count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
00154 if(count != 3) goto error;
00155 cur += chars_read;
00156 LLLandmark* lm = new LLLandmark;
00157 lm->mRegionID.set(region_id_str);
00158 lm->mRegionPos = pos;
00159 return lm;
00160 }
00161
00162 error:
00163 llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl;
00164 return NULL;
00165 }
00166
00167
00168
00169 void LLLandmark::registerCallbacks(LLMessageSystem* msg)
00170 {
00171 msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle);
00172 }
00173
00174
00175 void LLLandmark::requestRegionHandle(
00176 LLMessageSystem* msg,
00177 const LLHost& upstream_host,
00178 const LLUUID& region_id,
00179 LLRegionHandleCallback* callback)
00180 {
00181 if(region_id.isNull())
00182 {
00183
00184 lldebugs << "requestRegionHandle: null" << llendl;
00185 if(callback)
00186 {
00187 const U64 U64_ZERO = 0;
00188 callback->dataReady(region_id, U64_ZERO);
00189 }
00190 }
00191 else
00192 {
00193 if(region_id == mLocalRegion.first)
00194 {
00195 lldebugs << "requestRegionHandle: local" << llendl;
00196 if(callback)
00197 {
00198 callback->dataReady(region_id, mLocalRegion.second);
00199 }
00200 }
00201 else
00202 {
00203 region_map_t::iterator it = mRegions.find(region_id);
00204 if(it == mRegions.end())
00205 {
00206 lldebugs << "requestRegionHandle: upstream" << llendl;
00207 if(callback)
00208 {
00209 region_callback_t::value_type vt(region_id, callback);
00210 mRegionCallback.insert(vt);
00211 }
00212 lldebugs << "Landmark requesting information about: "
00213 << region_id << llendl;
00214 msg->newMessage("RegionHandleRequest");
00215 msg->nextBlock("RequestBlock");
00216 msg->addUUID("RegionID", region_id);
00217 msg->sendReliable(upstream_host);
00218 }
00219 else if(callback)
00220 {
00221
00222 lldebugs << "requestRegionHandle: ready" << llendl;
00223 callback->dataReady(region_id, (*it).second.mRegionHandle);
00224 }
00225 }
00226 }
00227
00228
00229 expireOldEntries();
00230 }
00231
00232
00233 void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle)
00234 {
00235 mLocalRegion.first = region_id;
00236 mLocalRegion.second = region_handle;
00237 }
00238
00239
00240
00241 void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
00242 {
00243 LLUUID region_id;
00244 msg->getUUID("ReplyBlock", "RegionID", region_id);
00245 mRegions.erase(region_id);
00246 CacheInfo info;
00247 const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f;
00248 info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS);
00249 msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle);
00250 region_map_t::value_type vt(region_id, info);
00251 mRegions.insert(vt);
00252
00253 #if LL_DEBUG
00254 U32 grid_x, grid_y;
00255 grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y);
00256 lldebugs << "Landmark got reply for region: " << region_id << " "
00257 << grid_x << "," << grid_y << llendl;
00258 #endif
00259
00260
00261 region_callback_t::iterator it;
00262 while((it = mRegionCallback.find(region_id)) != mRegionCallback.end())
00263 {
00264 (*it).second->dataReady(region_id, info.mRegionHandle);
00265 mRegionCallback.erase(it);
00266 }
00267 }
00268
00269
00270 void LLLandmark::expireOldEntries()
00271 {
00272 for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); )
00273 {
00274 if((*it).second.mTimer.hasExpired())
00275 {
00276 mRegions.erase(it++);
00277 }
00278 else
00279 {
00280 ++it;
00281 }
00282 }
00283 }