diff options
author | Jacek Antonelli | 2008-12-01 17:39:58 -0600 |
---|---|---|
committer | Jacek Antonelli | 2008-12-01 17:40:06 -0600 |
commit | 7abecb48babe6a6f09bf6692ba55076546cfced9 (patch) | |
tree | 8d18a88513fb97adf32c10aae78f4be1984942db /linden/indra/newview/llinventorymodel.cpp | |
parent | Second Life viewer sources 1.21.6 (diff) | |
download | meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.zip meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.gz meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.bz2 meta-impy-7abecb48babe6a6f09bf6692ba55076546cfced9.tar.xz |
Second Life viewer sources 1.22.0-RC
Diffstat (limited to 'linden/indra/newview/llinventorymodel.cpp')
-rw-r--r-- | linden/indra/newview/llinventorymodel.cpp | 536 |
1 files changed, 331 insertions, 205 deletions
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp index b1e3017..c3392ce 100644 --- a/linden/indra/newview/llinventorymodel.cpp +++ b/linden/indra/newview/llinventorymodel.cpp | |||
@@ -73,7 +73,6 @@ F32 LLInventoryModel::sMinTimeBetweenFetches = 0.3f; | |||
73 | F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f; | 73 | F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f; |
74 | BOOL LLInventoryModel::sTimelyFetchPending = FALSE; | 74 | BOOL LLInventoryModel::sTimelyFetchPending = FALSE; |
75 | LLFrameTimer LLInventoryModel::sFetchTimer; | 75 | LLFrameTimer LLInventoryModel::sFetchTimer; |
76 | LLInventoryModel::cat_map_t LLInventoryModel::sBulkFetchMap; | ||
77 | S16 LLInventoryModel::sBulkFetchCount = 0; | 76 | S16 LLInventoryModel::sBulkFetchCount = 0; |
78 | 77 | ||
79 | // RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue | 78 | // RN: for some reason, using std::queue in the header file confuses the compiler which things it's an xmlrpc_queue |
@@ -85,7 +84,7 @@ static std::deque<LLUUID> sFetchQueue; | |||
85 | 84 | ||
86 | //BOOL decompress_file(const char* src_filename, const char* dst_filename); | 85 | //BOOL decompress_file(const char* src_filename, const char* dst_filename); |
87 | const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; | 86 | const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f; |
88 | const S32 MAX_FETCH_RETRIES = 5; | 87 | const S32 MAX_FETCH_RETRIES = 10; |
89 | const char CACHE_FORMAT_STRING[] = "%s.inv"; | 88 | const char CACHE_FORMAT_STRING[] = "%s.inv"; |
90 | const char* NEW_CATEGORY_NAME = "New Folder"; | 89 | const char* NEW_CATEGORY_NAME = "New Folder"; |
91 | const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] = | 90 | const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] = |
@@ -990,13 +989,24 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) | |||
990 | // Call this method when it's time to update everyone on a new state, | 989 | // Call this method when it's time to update everyone on a new state, |
991 | // by default, the inventory model will not update observers | 990 | // by default, the inventory model will not update observers |
992 | // automatically. | 991 | // automatically. |
993 | void LLInventoryModel::notifyObservers() | 992 | // The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328] |
993 | void LLInventoryModel::notifyObservers(const std::string service_name) | ||
994 | { | 994 | { |
995 | for (observer_list_t::iterator iter = mObservers.begin(); | 995 | for (observer_list_t::iterator iter = mObservers.begin(); |
996 | iter != mObservers.end(); ) | 996 | iter != mObservers.end(); ) |
997 | { | 997 | { |
998 | LLInventoryObserver* observer = *iter; | 998 | LLInventoryObserver* observer = *iter; |
999 | observer->changed(mModifyMask); | 999 | |
1000 | if (service_name.empty()) | ||
1001 | { | ||
1002 | observer->changed(mModifyMask); | ||
1003 | } | ||
1004 | else | ||
1005 | { | ||
1006 | observer->mMessageName = service_name; | ||
1007 | observer->changed(mModifyMask); | ||
1008 | } | ||
1009 | |||
1000 | // safe way to incrament since changed may delete entries! (@!##%@!@&*!) | 1010 | // safe way to incrament since changed may delete entries! (@!##%@!@&*!) |
1001 | iter = mObservers.upper_bound(observer); | 1011 | iter = mObservers.upper_bound(observer); |
1002 | } | 1012 | } |
@@ -1038,6 +1048,79 @@ void LLInventoryModel::mock(const LLUUID& root_id) | |||
1038 | } | 1048 | } |
1039 | */ | 1049 | */ |
1040 | 1050 | ||
1051 | //If we get back a normal response, handle it here | ||
1052 | void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) | ||
1053 | { | ||
1054 | start_new_inventory_observer(); | ||
1055 | |||
1056 | /*LLUUID agent_id; | ||
1057 | agent_id = content["agent_id"].asUUID(); | ||
1058 | if(agent_id != gAgent.getID()) | ||
1059 | { | ||
1060 | llwarns << "Got a inventory update for the wrong agent: " << agent_id | ||
1061 | << llendl; | ||
1062 | return; | ||
1063 | }*/ | ||
1064 | item_array_t items; | ||
1065 | update_map_t update; | ||
1066 | S32 count = content["items"].size(); | ||
1067 | bool all_one_folder = true; | ||
1068 | LLUUID folder_id; | ||
1069 | // Does this loop ever execute more than once? -Gigs | ||
1070 | for(S32 i = 0; i < count; ++i) | ||
1071 | { | ||
1072 | LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; | ||
1073 | titem->unpackMessage(content["items"][i]); | ||
1074 | |||
1075 | lldebugs << "LLInventoryModel::messageUpdateCore() item id:" | ||
1076 | << titem->getUUID() << llendl; | ||
1077 | items.push_back(titem); | ||
1078 | // examine update for changes. | ||
1079 | LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID()); | ||
1080 | if(itemp) | ||
1081 | { | ||
1082 | if(titem->getParentUUID() == itemp->getParentUUID()) | ||
1083 | { | ||
1084 | update[titem->getParentUUID()]; | ||
1085 | } | ||
1086 | else | ||
1087 | { | ||
1088 | ++update[titem->getParentUUID()]; | ||
1089 | --update[itemp->getParentUUID()]; | ||
1090 | } | ||
1091 | } | ||
1092 | else | ||
1093 | { | ||
1094 | ++update[titem->getParentUUID()]; | ||
1095 | } | ||
1096 | if (folder_id.isNull()) | ||
1097 | { | ||
1098 | folder_id = titem->getParentUUID(); | ||
1099 | } | ||
1100 | else | ||
1101 | { | ||
1102 | all_one_folder = false; | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | U32 changes = 0x0; | ||
1107 | //as above, this loop never seems to loop more than once per call | ||
1108 | for (item_array_t::iterator it = items.begin(); it != items.end(); ++it) | ||
1109 | { | ||
1110 | changes |= gInventory.updateItem(*it); | ||
1111 | } | ||
1112 | gInventory.notifyObservers("fetchinventory"); | ||
1113 | gViewerWindow->getWindow()->decBusyCount(); | ||
1114 | } | ||
1115 | |||
1116 | //If we get back an error (not found, etc...), handle it here | ||
1117 | void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason) | ||
1118 | { | ||
1119 | llinfos << "fetchInventory::error " | ||
1120 | << status << ": " << reason << llendl; | ||
1121 | gInventory.notifyObservers("fetchinventory"); | ||
1122 | } | ||
1123 | |||
1041 | void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) | 1124 | void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) |
1042 | { | 1125 | { |
1043 | LLViewerInventoryCategory* cat = getCategory(folder_id); | 1126 | LLViewerInventoryCategory* cat = getCategory(folder_id); |
@@ -1065,21 +1148,31 @@ void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) | |||
1065 | } | 1148 | } |
1066 | 1149 | ||
1067 | //Initialize statics. | 1150 | //Initialize statics. |
1068 | LLAlertDialog* LLInventoryModel::fetchDescendentsResponder::sRetryDialog=NULL; | ||
1069 | LLSD LLInventoryModel::fetchDescendentsResponder::sRetrySD; | ||
1070 | |||
1071 | bool LLInventoryModel::isBulkFetchProcessingComplete() | 1151 | bool LLInventoryModel::isBulkFetchProcessingComplete() |
1072 | { | 1152 | { |
1073 | return ( (sFetchQueue.empty() | 1153 | return ( (sFetchQueue.empty() |
1074 | && sBulkFetchMap.empty() | 1154 | && sBulkFetchCount<=0) ? TRUE : FALSE ) ; |
1075 | && sBulkFetchCount==0) ? TRUE : FALSE ) ; | ||
1076 | } | 1155 | } |
1077 | 1156 | ||
1157 | class fetchDescendentsResponder: public LLHTTPClient::Responder | ||
1158 | { | ||
1159 | public: | ||
1160 | fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; | ||
1161 | //fetchDescendentsResponder() {}; | ||
1162 | void result(const LLSD& content); | ||
1163 | void error(U32 status, const std::string& reason); | ||
1164 | public: | ||
1165 | typedef std::vector<LLViewerInventoryCategory*> folder_ref_t; | ||
1166 | protected: | ||
1167 | LLSD mRequestSD; | ||
1168 | }; | ||
1169 | |||
1078 | //If we get back a normal response, handle it here | 1170 | //If we get back a normal response, handle it here |
1079 | void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content) | 1171 | void fetchDescendentsResponder::result(const LLSD& content) |
1080 | { | 1172 | { |
1081 | if (content.has("folders")) | 1173 | if (content.has("folders")) |
1082 | { | 1174 | { |
1175 | |||
1083 | for(LLSD::array_const_iterator folder_it = content["folders"].beginArray(); | 1176 | for(LLSD::array_const_iterator folder_it = content["folders"].beginArray(); |
1084 | folder_it != content["folders"].endArray(); | 1177 | folder_it != content["folders"].endArray(); |
1085 | ++folder_it) | 1178 | ++folder_it) |
@@ -1087,19 +1180,54 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content) | |||
1087 | LLSD folder_sd = *folder_it; | 1180 | LLSD folder_sd = *folder_it; |
1088 | 1181 | ||
1089 | 1182 | ||
1090 | LLUUID agent_id = folder_sd["agent-id"]; | 1183 | //LLUUID agent_id = folder_sd["agent_id"]; |
1091 | 1184 | ||
1092 | if(agent_id != gAgent.getID()) //This should never happen. | 1185 | //if(agent_id != gAgent.getID()) //This should never happen. |
1093 | { | 1186 | //{ |
1094 | llwarns << "Got a UpdateInventoryItem for the wrong agent." | 1187 | // llwarns << "Got a UpdateInventoryItem for the wrong agent." |
1095 | << llendl; | 1188 | // << llendl; |
1096 | break; | 1189 | // break; |
1097 | } | 1190 | //} |
1098 | LLUUID parent_id = folder_sd["folder-id"]; | 1191 | |
1099 | LLUUID owner_id = folder_sd["owner-id"]; | 1192 | LLUUID parent_id = folder_sd["folder_id"]; |
1193 | LLUUID owner_id = folder_sd["owner_id"]; | ||
1100 | S32 version = (S32)folder_sd["version"].asInteger(); | 1194 | S32 version = (S32)folder_sd["version"].asInteger(); |
1101 | S32 descendents = (S32)folder_sd["descendents"].asInteger(); | 1195 | S32 descendents = (S32)folder_sd["descendents"].asInteger(); |
1102 | LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id); | 1196 | LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id); |
1197 | |||
1198 | if (parent_id.isNull()) | ||
1199 | { | ||
1200 | LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem; | ||
1201 | for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray(); | ||
1202 | item_it != folder_sd["items"].endArray(); | ||
1203 | ++item_it) | ||
1204 | { | ||
1205 | LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); | ||
1206 | if (lost_uuid.notNull()) | ||
1207 | { | ||
1208 | LLSD item = *item_it; | ||
1209 | titem->unpackMessage(item); | ||
1210 | |||
1211 | LLInventoryModel::update_list_t update; | ||
1212 | LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1); | ||
1213 | update.push_back(new_folder); | ||
1214 | gInventory.accountForUpdate(update); | ||
1215 | |||
1216 | titem->setParent(lost_uuid); | ||
1217 | titem->updateParentOnServer(FALSE); | ||
1218 | gInventory.updateItem(titem); | ||
1219 | gInventory.notifyObservers("fetchDescendents"); | ||
1220 | |||
1221 | } | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id); | ||
1226 | if (!pcat) | ||
1227 | { | ||
1228 | continue; | ||
1229 | } | ||
1230 | |||
1103 | for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray(); | 1231 | for(LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray(); |
1104 | category_it != folder_sd["categories"].endArray(); | 1232 | category_it != folder_sd["categories"].endArray(); |
1105 | ++category_it) | 1233 | ++category_it) |
@@ -1107,7 +1235,7 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content) | |||
1107 | LLSD category = *category_it; | 1235 | LLSD category = *category_it; |
1108 | tcategory->fromLLSD(category); | 1236 | tcategory->fromLLSD(category); |
1109 | 1237 | ||
1110 | if (sFullFetchStarted) | 1238 | if (LLInventoryModel::sFullFetchStarted) |
1111 | { | 1239 | { |
1112 | sFetchQueue.push_back(tcategory->getUUID()); | 1240 | sFetchQueue.push_back(tcategory->getUUID()); |
1113 | } | 1241 | } |
@@ -1139,37 +1267,37 @@ void LLInventoryModel::fetchDescendentsResponder::result(const LLSD& content) | |||
1139 | } | 1267 | } |
1140 | } | 1268 | } |
1141 | 1269 | ||
1142 | if (content.has("bad-folders")) | 1270 | if (content.has("bad_folders")) |
1143 | { | 1271 | { |
1144 | for(LLSD::array_const_iterator folder_it = content["bad-folders"].beginArray(); | 1272 | for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray(); |
1145 | folder_it != content["bad-folders"].endArray(); | 1273 | folder_it != content["bad_folders"].endArray(); |
1146 | ++folder_it) | 1274 | ++folder_it) |
1147 | { | 1275 | { |
1148 | LLSD folder_sd = *folder_it; | 1276 | LLSD folder_sd = *folder_it; |
1149 | 1277 | ||
1150 | //These folders failed on the dataserver. We probably don't want to retry them. | 1278 | //These folders failed on the dataserver. We probably don't want to retry them. |
1151 | llinfos << "Folder " << folder_sd["folder-id"].asString() | 1279 | llinfos << "Folder " << folder_sd["folder_id"].asString() |
1152 | << "Error: " << folder_sd["error"].asString() << llendl; | 1280 | << "Error: " << folder_sd["error"].asString() << llendl; |
1153 | } | 1281 | } |
1154 | } | 1282 | } |
1155 | 1283 | ||
1156 | LLInventoryModel::incrBulkFetch(-1); | 1284 | LLInventoryModel::incrBulkFetch(-1); |
1157 | 1285 | ||
1158 | if (isBulkFetchProcessingComplete()) | 1286 | if (LLInventoryModel::isBulkFetchProcessingComplete()) |
1159 | { | 1287 | { |
1160 | llinfos << "Inventory fetch completed" << llendl; | 1288 | llinfos << "Inventory fetch completed" << llendl; |
1161 | if (sFullFetchStarted) | 1289 | if (LLInventoryModel::sFullFetchStarted) |
1162 | { | 1290 | { |
1163 | sAllFoldersFetched = TRUE; | 1291 | LLInventoryModel::sAllFoldersFetched = TRUE; |
1164 | } | 1292 | } |
1165 | stopBackgroundFetch(); | 1293 | LLInventoryModel::stopBackgroundFetch(); |
1166 | } | 1294 | } |
1167 | 1295 | ||
1168 | gInventory.notifyObservers(); | 1296 | gInventory.notifyObservers("fetchDescendents"); |
1169 | } | 1297 | } |
1170 | 1298 | ||
1171 | //If we get back an error (not found, etc...), handle it here | 1299 | //If we get back an error (not found, etc...), handle it here |
1172 | void LLInventoryModel::fetchDescendentsResponder::error(U32 status, const std::string& reason) | 1300 | void fetchDescendentsResponder::error(U32 status, const std::string& reason) |
1173 | { | 1301 | { |
1174 | llinfos << "fetchDescendentsResponder::error " | 1302 | llinfos << "fetchDescendentsResponder::error " |
1175 | << status << ": " << reason << llendl; | 1303 | << status << ": " << reason << llendl; |
@@ -1183,61 +1311,22 @@ void LLInventoryModel::fetchDescendentsResponder::error(U32 status, const std::s | |||
1183 | ++folder_it) | 1311 | ++folder_it) |
1184 | { | 1312 | { |
1185 | LLSD folder_sd = *folder_it; | 1313 | LLSD folder_sd = *folder_it; |
1186 | sRetrySD["folders"].append(folder_sd); | 1314 | LLUUID folder_id = folder_sd["folder_id"]; |
1187 | } | 1315 | sFetchQueue.push_front(folder_id); |
1188 | sMinTimeBetweenFetches = 10.0f; //Add 10 seconds for every time out in this sequence. | ||
1189 | |||
1190 | if (!sRetryDialog) //The dialog isn't up. Prompt the resident. | ||
1191 | { | ||
1192 | sRetryDialog = gViewerWindow->alertXml("RetryFetchInventoryDescendents", onClickRetry, this); | ||
1193 | } | 1316 | } |
1194 | } | 1317 | } |
1195 | else | 1318 | else |
1196 | { | 1319 | { |
1197 | if (isBulkFetchProcessingComplete()) | 1320 | if (LLInventoryModel::isBulkFetchProcessingComplete()) |
1198 | { | 1321 | { |
1199 | if (sFullFetchStarted) | 1322 | if (LLInventoryModel::sFullFetchStarted) |
1200 | { | 1323 | { |
1201 | sAllFoldersFetched = TRUE; | 1324 | LLInventoryModel::sAllFoldersFetched = TRUE; |
1202 | } | 1325 | } |
1203 | stopBackgroundFetch(); | 1326 | LLInventoryModel::stopBackgroundFetch(); |
1204 | } | 1327 | } |
1205 | } | 1328 | } |
1206 | gInventory.notifyObservers(); | 1329 | gInventory.notifyObservers("fetchDescendents"); |
1207 | } | ||
1208 | |||
1209 | void LLInventoryModel::fetchDescendentsResponder::onClickRetry(S32 option, void* userdata) | ||
1210 | { | ||
1211 | if (option == 0) | ||
1212 | { | ||
1213 | std::string url; | ||
1214 | |||
1215 | LLViewerRegion * agent_region = gAgent.getRegion(); | ||
1216 | if (agent_region) | ||
1217 | { | ||
1218 | url = agent_region->getCapability("FetchInventoryDescendents"); | ||
1219 | } | ||
1220 | |||
1221 | if (!url.empty()) //Capability found. Build up LLSD and use it. | ||
1222 | { | ||
1223 | LLSD body = sRetrySD; | ||
1224 | LLInventoryModel::incrBulkFetch(1); | ||
1225 | LLHTTPClient::post(url, body, new LLInventoryModel::fetchDescendentsResponder(body),300); | ||
1226 | } | ||
1227 | } | ||
1228 | else | ||
1229 | { | ||
1230 | if (isBulkFetchProcessingComplete()) | ||
1231 | { | ||
1232 | if (sFullFetchStarted) | ||
1233 | { | ||
1234 | sAllFoldersFetched = TRUE; | ||
1235 | } | ||
1236 | stopBackgroundFetch(); | ||
1237 | } | ||
1238 | } | ||
1239 | sRetryDialog=NULL; | ||
1240 | sRetrySD.clear(); | ||
1241 | } | 1330 | } |
1242 | 1331 | ||
1243 | //static Bundle up a bunch of requests to send all at once. | 1332 | //static Bundle up a bunch of requests to send all at once. |
@@ -1250,7 +1339,7 @@ void LLInventoryModel::bulkFetch(std::string url) | |||
1250 | 1339 | ||
1251 | S16 max_concurrent_fetches=8; | 1340 | S16 max_concurrent_fetches=8; |
1252 | F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. | 1341 | F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. |
1253 | if (sMinTimeBetweenFetches <= new_min_time) sMinTimeBetweenFetches=new_min_time; //HACK! See above. | 1342 | if (sMinTimeBetweenFetches < new_min_time) sMinTimeBetweenFetches=new_min_time; //HACK! See above. |
1254 | 1343 | ||
1255 | if(gDisconnected | 1344 | if(gDisconnected |
1256 | || sBulkFetchCount > max_concurrent_fetches | 1345 | || sBulkFetchCount > max_concurrent_fetches |
@@ -1259,88 +1348,84 @@ void LLInventoryModel::bulkFetch(std::string url) | |||
1259 | return; // just bail if we are disconnected. | 1348 | return; // just bail if we are disconnected. |
1260 | } | 1349 | } |
1261 | 1350 | ||
1262 | //HACK. This is inelegant. We're shuffling a dequeue to a map to get rid of | ||
1263 | //redundant requests. When we get rid of the old code entirely, we can change | ||
1264 | //the dequeue to a map. In the new model, there is no benefit to queue order. | ||
1265 | U32 folder_count=0; | 1351 | U32 folder_count=0; |
1266 | U32 max_batch_size=10; | 1352 | U32 max_batch_size=5; |
1267 | while( !(sFetchQueue.empty() ) ) | 1353 | |
1268 | { | 1354 | U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1; |
1269 | LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); | 1355 | |
1270 | 1356 | LLSD body; | |
1271 | if (cat) | 1357 | LLSD body_lib; |
1272 | { | 1358 | while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) ) |
1273 | if ( !gInventory.isCategoryComplete(cat->getUUID()) ) //grab this folder. | 1359 | { |
1274 | { | 1360 | if (sFetchQueue.front().isNull()) //DEV-17797 |
1275 | sBulkFetchMap[(cat->getUUID())] = cat; | 1361 | { |
1276 | } | 1362 | LLSD folder_sd; |
1277 | else if (sFullFetchStarted) | 1363 | folder_sd["folder_id"] = LLUUID::null.asString(); |
1278 | { //Already have this folder but append child folders to list. | 1364 | folder_sd["owner_id"] = gAgent.getID(); |
1279 | // add all children to queue | 1365 | folder_sd["sort_order"] = (LLSD::Integer)sort_order; |
1280 | parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); | 1366 | folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE; |
1281 | if (cat_it != gInventory.mParentChildCategoryTree.end()) | 1367 | folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; |
1282 | { | 1368 | body["folders"].append(folder_sd); |
1283 | cat_array_t* child_categories = cat_it->second; | 1369 | folder_count++; |
1284 | 1370 | } | |
1285 | for (S32 child_num = 0; child_num < child_categories->count(); child_num++) | 1371 | else |
1286 | { | 1372 | { |
1287 | sFetchQueue.push_back(child_categories->get(child_num)->getUUID()); | 1373 | |
1288 | } | ||
1289 | } | ||
1290 | 1374 | ||
1291 | } | 1375 | LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front()); |
1292 | } | 1376 | |
1377 | if (cat) | ||
1378 | { | ||
1379 | if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) | ||
1380 | { | ||
1381 | LLSD folder_sd; | ||
1382 | folder_sd["folder_id"] = cat->getUUID(); | ||
1383 | folder_sd["owner_id"] = cat->getOwnerID(); | ||
1384 | folder_sd["sort_order"] = (LLSD::Integer)sort_order; | ||
1385 | folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted; | ||
1386 | folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; | ||
1387 | |||
1388 | if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) | ||
1389 | body_lib["folders"].append(folder_sd); | ||
1390 | else | ||
1391 | body["folders"].append(folder_sd); | ||
1392 | folder_count++; | ||
1393 | } | ||
1394 | if (sFullFetchStarted) | ||
1395 | { //Already have this folder but append child folders to list. | ||
1396 | // add all children to queue | ||
1397 | parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID()); | ||
1398 | if (cat_it != gInventory.mParentChildCategoryTree.end()) | ||
1399 | { | ||
1400 | cat_array_t* child_categories = cat_it->second; | ||
1401 | |||
1402 | for (S32 child_num = 0; child_num < child_categories->count(); child_num++) | ||
1403 | { | ||
1404 | sFetchQueue.push_back(child_categories->get(child_num)->getUUID()); | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | } | ||
1409 | } | ||
1410 | } | ||
1293 | sFetchQueue.pop_front(); | 1411 | sFetchQueue.pop_front(); |
1294 | } | 1412 | } |
1295 | 1413 | ||
1296 | |||
1297 | if (!sBulkFetchMap.empty()) //There's stuff to fetch. | ||
1298 | { | ||
1299 | U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1; | ||
1300 | |||
1301 | LLSD body; | ||
1302 | |||
1303 | cat_map_t::iterator iter=sBulkFetchMap.begin(); | ||
1304 | while( iter!=sBulkFetchMap.end() && (folder_count < max_batch_size) ) | ||
1305 | { | ||
1306 | LLViewerInventoryCategory* cat = iter->second; | ||
1307 | |||
1308 | if (cat && !gInventory.isCategoryComplete(cat->getUUID()) ) //Category exists | ||
1309 | { | ||
1310 | BOOL fetchItems=TRUE; | ||
1311 | if ( sFullFetchStarted | ||
1312 | && gInventory.isCategoryComplete(cat->getUUID()) ) | ||
1313 | { | ||
1314 | fetchItems=FALSE; | ||
1315 | } | ||
1316 | |||
1317 | LLSD folder_sd; | ||
1318 | folder_sd["folder-id"] = cat->getUUID(); | ||
1319 | folder_sd["owner-id"] = cat->getOwnerID(); | ||
1320 | folder_sd["sort-order"] = (LLSD::Integer)sort_order; | ||
1321 | folder_sd["fetch-folders"] = (LLSD::Boolean)sFullFetchStarted; | ||
1322 | folder_sd["fetch-items"] = (LLSD::Boolean)fetchItems; | ||
1323 | body["folders"].append(folder_sd); | ||
1324 | |||
1325 | folder_count++; | ||
1326 | } | ||
1327 | sBulkFetchMap.erase(iter); | ||
1328 | iter=sBulkFetchMap.begin(); | ||
1329 | } | ||
1330 | |||
1331 | if (iter == sBulkFetchMap.end()) sBulkFetchMap.clear(); | ||
1332 | |||
1333 | if (folder_count > 0) | 1414 | if (folder_count > 0) |
1334 | { | 1415 | { |
1335 | sBulkFetchCount++; | 1416 | sBulkFetchCount++; |
1336 | 1417 | if (body["folders"].size()) | |
1337 | LLHTTPClient::post(url, body, new LLInventoryModel::fetchDescendentsResponder(body)); | 1418 | { |
1419 | LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0); | ||
1420 | } | ||
1421 | if (body_lib["folders"].size()) | ||
1422 | { | ||
1423 | std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); | ||
1424 | LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0); | ||
1425 | } | ||
1338 | sFetchTimer.reset(); | 1426 | sFetchTimer.reset(); |
1339 | } | 1427 | } |
1340 | 1428 | else if (isBulkFetchProcessingComplete()) | |
1341 | } | ||
1342 | |||
1343 | if (isBulkFetchProcessingComplete()) | ||
1344 | { | 1429 | { |
1345 | if (sFullFetchStarted) | 1430 | if (sFullFetchStarted) |
1346 | { | 1431 | { |
@@ -1391,6 +1476,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) | |||
1391 | } | 1476 | } |
1392 | 1477 | ||
1393 | //static | 1478 | //static |
1479 | void LLInventoryModel::findLostItems() | ||
1480 | { | ||
1481 | sBackgroundFetchActive = TRUE; | ||
1482 | sFetchQueue.push_back(LLUUID::null); | ||
1483 | gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); | ||
1484 | } | ||
1485 | |||
1486 | //static | ||
1394 | void LLInventoryModel::stopBackgroundFetch() | 1487 | void LLInventoryModel::stopBackgroundFetch() |
1395 | { | 1488 | { |
1396 | if (sBackgroundFetchActive) | 1489 | if (sBackgroundFetchActive) |
@@ -1409,14 +1502,7 @@ void LLInventoryModel::backgroundFetch(void*) | |||
1409 | if (sBackgroundFetchActive) | 1502 | if (sBackgroundFetchActive) |
1410 | { | 1503 | { |
1411 | //If we'll be using the capability, we'll be sending batches and the background thing isn't as important. | 1504 | //If we'll be using the capability, we'll be sending batches and the background thing isn't as important. |
1412 | std::string url; | 1505 | std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); |
1413 | |||
1414 | LLViewerRegion * agent_region = gAgent.getRegion(); | ||
1415 | if (agent_region) | ||
1416 | { | ||
1417 | url = agent_region->getCapability("FetchInventoryDescendents"); | ||
1418 | } | ||
1419 | |||
1420 | if (!url.empty()) | 1506 | if (!url.empty()) |
1421 | { | 1507 | { |
1422 | bulkFetch(url); | 1508 | bulkFetch(url); |
@@ -3373,12 +3459,72 @@ bool LLInventoryFetchObserver::isEverythingComplete() const | |||
3373 | return mIncomplete.empty(); | 3459 | return mIncomplete.empty(); |
3374 | } | 3460 | } |
3375 | 3461 | ||
3462 | void fetch_items_from_llsd(const LLSD& items_llsd) | ||
3463 | { | ||
3464 | if (!items_llsd.size()) return; | ||
3465 | LLSD body; | ||
3466 | body[0]["cap_name"] = "FetchInventory"; | ||
3467 | body[1]["cap_name"] = "FetchLib"; | ||
3468 | for (S32 i=0; i<items_llsd.size();i++) | ||
3469 | { | ||
3470 | if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString()) | ||
3471 | { | ||
3472 | body[0]["items"].append(items_llsd[i]); | ||
3473 | continue; | ||
3474 | } | ||
3475 | if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString()) | ||
3476 | { | ||
3477 | body[1]["items"].append(items_llsd[i]); | ||
3478 | continue; | ||
3479 | } | ||
3480 | } | ||
3481 | |||
3482 | for (S32 i=0; i<body.size(); i++) | ||
3483 | { | ||
3484 | if (0 >= body[i].size()) continue; | ||
3485 | std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString()); | ||
3486 | |||
3487 | if (!url.empty()) | ||
3488 | { | ||
3489 | body[i]["agent_id"] = gAgent.getID(); | ||
3490 | LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i])); | ||
3491 | break; | ||
3492 | } | ||
3493 | |||
3494 | LLMessageSystem* msg = gMessageSystem; | ||
3495 | BOOL start_new_message = TRUE; | ||
3496 | for (S32 j=0; j<body[i]["items"].size(); j++) | ||
3497 | { | ||
3498 | LLSD item_entry = body[i]["items"][j]; | ||
3499 | if(start_new_message) | ||
3500 | { | ||
3501 | start_new_message = FALSE; | ||
3502 | msg->newMessageFast(_PREHASH_FetchInventory); | ||
3503 | msg->nextBlockFast(_PREHASH_AgentData); | ||
3504 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
3505 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
3506 | } | ||
3507 | msg->nextBlockFast(_PREHASH_InventoryData); | ||
3508 | msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID()); | ||
3509 | msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID()); | ||
3510 | if(msg->isSendFull(NULL)) | ||
3511 | { | ||
3512 | start_new_message = TRUE; | ||
3513 | gAgent.sendReliableMessage(); | ||
3514 | } | ||
3515 | } | ||
3516 | if(!start_new_message) | ||
3517 | { | ||
3518 | gAgent.sendReliableMessage(); | ||
3519 | } | ||
3520 | } | ||
3521 | } | ||
3522 | |||
3376 | void LLInventoryFetchObserver::fetchItems( | 3523 | void LLInventoryFetchObserver::fetchItems( |
3377 | const LLInventoryFetchObserver::item_ref_t& ids) | 3524 | const LLInventoryFetchObserver::item_ref_t& ids) |
3378 | { | 3525 | { |
3379 | LLMessageSystem* msg = gMessageSystem; | ||
3380 | BOOL start_new_message = TRUE; | ||
3381 | LLUUID owner_id; | 3526 | LLUUID owner_id; |
3527 | LLSD items_llsd; | ||
3382 | for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) | 3528 | for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it) |
3383 | { | 3529 | { |
3384 | LLViewerInventoryItem* item = gInventory.getItem(*it); | 3530 | LLViewerInventoryItem* item = gInventory.getItem(*it); |
@@ -3400,31 +3546,18 @@ void LLInventoryFetchObserver::fetchItems( | |||
3400 | // assume it's agent inventory. | 3546 | // assume it's agent inventory. |
3401 | owner_id = gAgent.getID(); | 3547 | owner_id = gAgent.getID(); |
3402 | } | 3548 | } |
3403 | 3549 | ||
3404 | // It's incomplete, so put it on the incomplete container, and | 3550 | // It's incomplete, so put it on the incomplete container, and |
3405 | // pack this on the message. | 3551 | // pack this on the message. |
3406 | mIncomplete.push_back(*it); | 3552 | mIncomplete.push_back(*it); |
3407 | if(start_new_message) | 3553 | |
3408 | { | 3554 | // Prepare the data to fetch |
3409 | start_new_message = FALSE; | 3555 | LLSD item_entry; |
3410 | msg->newMessageFast(_PREHASH_FetchInventory); | 3556 | item_entry["owner_id"] = owner_id; |
3411 | msg->nextBlockFast(_PREHASH_AgentData); | 3557 | item_entry["item_id"] = (*it); |
3412 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | 3558 | items_llsd.append(item_entry); |
3413 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
3414 | } | ||
3415 | msg->nextBlockFast(_PREHASH_InventoryData); | ||
3416 | msg->addUUIDFast(_PREHASH_OwnerID, owner_id); | ||
3417 | msg->addUUIDFast(_PREHASH_ItemID, (*it)); | ||
3418 | if(msg->isSendFull(NULL)) | ||
3419 | { | ||
3420 | start_new_message = TRUE; | ||
3421 | gAgent.sendReliableMessage(); | ||
3422 | } | ||
3423 | } | ||
3424 | if(!start_new_message) | ||
3425 | { | ||
3426 | gAgent.sendReliableMessage(); | ||
3427 | } | 3559 | } |
3560 | fetch_items_from_llsd(items_llsd); | ||
3428 | } | 3561 | } |
3429 | 3562 | ||
3430 | // virtual | 3563 | // virtual |
@@ -3579,9 +3712,8 @@ void LLInventoryFetchComboObserver::fetch( | |||
3579 | // descendent of an incomplete folder because the item will show | 3712 | // descendent of an incomplete folder because the item will show |
3580 | // up in an inventory descendents message soon enough so we do not | 3713 | // up in an inventory descendents message soon enough so we do not |
3581 | // have to fetch it individually. | 3714 | // have to fetch it individually. |
3715 | LLSD items_llsd; | ||
3582 | LLUUID owner_id; | 3716 | LLUUID owner_id; |
3583 | LLMessageSystem* msg = gMessageSystem; | ||
3584 | bool start_new_message = true; | ||
3585 | for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit) | 3717 | for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit) |
3586 | { | 3718 | { |
3587 | LLViewerInventoryItem* item = gInventory.getItem(*iit); | 3719 | LLViewerInventoryItem* item = gInventory.getItem(*iit); |
@@ -3604,33 +3736,17 @@ void LLInventoryFetchComboObserver::fetch( | |||
3604 | } | 3736 | } |
3605 | if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) | 3737 | if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) |
3606 | { | 3738 | { |
3607 | lldebugs << "fetching item " << *iit << llendl; | 3739 | LLSD item_entry; |
3608 | if(start_new_message) | 3740 | item_entry["owner_id"] = owner_id; |
3609 | { | 3741 | item_entry["item_id"] = (*iit); |
3610 | start_new_message = false; | 3742 | items_llsd.append(item_entry); |
3611 | msg->newMessageFast(_PREHASH_FetchInventory); | ||
3612 | msg->nextBlockFast(_PREHASH_AgentData); | ||
3613 | msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
3614 | msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
3615 | } | ||
3616 | msg->nextBlockFast(_PREHASH_InventoryData); | ||
3617 | msg->addUUIDFast(_PREHASH_OwnerID, owner_id); | ||
3618 | msg->addUUIDFast(_PREHASH_ItemID, (*iit)); | ||
3619 | if(msg->isSendFullFast(_PREHASH_InventoryData)) | ||
3620 | { | ||
3621 | start_new_message = true; | ||
3622 | gAgent.sendReliableMessage(); | ||
3623 | } | ||
3624 | } | 3743 | } |
3625 | else | 3744 | else |
3626 | { | 3745 | { |
3627 | lldebugs << "not worrying about " << *iit << llendl; | 3746 | lldebugs << "not worrying about " << *iit << llendl; |
3628 | } | 3747 | } |
3629 | } | 3748 | } |
3630 | if(!start_new_message) | 3749 | fetch_items_from_llsd(items_llsd); |
3631 | { | ||
3632 | gAgent.sendReliableMessage(); | ||
3633 | } | ||
3634 | } | 3750 | } |
3635 | 3751 | ||
3636 | void LLInventoryExistenceObserver::watchItem(const LLUUID& id) | 3752 | void LLInventoryExistenceObserver::watchItem(const LLUUID& id) |
@@ -3676,7 +3792,17 @@ void LLInventoryAddedObserver::changed(U32 mask) | |||
3676 | // the network, figure out which item was updated. | 3792 | // the network, figure out which item was updated. |
3677 | // Code from Gigs Taggert, sin allowed by JC. | 3793 | // Code from Gigs Taggert, sin allowed by JC. |
3678 | LLMessageSystem* msg = gMessageSystem; | 3794 | LLMessageSystem* msg = gMessageSystem; |
3679 | std::string msg_name = msg->getMessageName(); | 3795 | |
3796 | std::string msg_name; | ||
3797 | if (mMessageName.empty()) | ||
3798 | { | ||
3799 | msg_name = msg->getMessageName(); | ||
3800 | } | ||
3801 | else | ||
3802 | { | ||
3803 | msg_name = mMessageName; | ||
3804 | } | ||
3805 | |||
3680 | if (msg_name.empty()) | 3806 | if (msg_name.empty()) |
3681 | { | 3807 | { |
3682 | return; | 3808 | return; |