aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services')
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs211
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs5
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs4
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs223
5 files changed, 361 insertions, 88 deletions
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index 7ac7917..99119d3 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -46,10 +46,13 @@ namespace OpenSim.Services.Connectors
46 LogManager.GetLogger( 46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 47 MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 const int MAXSENDRETRIESLEN = 30;
50
49 private string m_ServerURI = String.Empty; 51 private string m_ServerURI = String.Empty;
50 private IImprovedAssetCache m_Cache = null; 52 private IImprovedAssetCache m_Cache = null;
51 private int m_retryCounter; 53 private int m_retryCounter;
52 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>(); 54 private bool m_inRetries;
55 private List<AssetBase>[] m_sendRetries = new List<AssetBase>[MAXSENDRETRIESLEN];
53 private System.Timers.Timer m_retryTimer; 56 private System.Timers.Timer m_retryTimer;
54 private int m_maxAssetRequestConcurrency = 30; 57 private int m_maxAssetRequestConcurrency = 30;
55 58
@@ -110,9 +113,9 @@ namespace OpenSim.Services.Connectors
110 throw new Exception("Asset connector init error"); 113 throw new Exception("Asset connector init error");
111 } 114 }
112 115
113
114 m_retryTimer = new System.Timers.Timer(); 116 m_retryTimer = new System.Timers.Timer();
115 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck); 117 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
118 m_retryTimer.AutoReset = true;
116 m_retryTimer.Interval = 60000; 119 m_retryTimer.Interval = 60000;
117 120
118 Uri serverUri = new Uri(m_ServerURI); 121 Uri serverUri = new Uri(m_ServerURI);
@@ -166,48 +169,67 @@ namespace OpenSim.Services.Connectors
166 169
167 protected void retryCheck(object source, ElapsedEventArgs e) 170 protected void retryCheck(object source, ElapsedEventArgs e)
168 { 171 {
169 m_retryCounter++; 172 lock(m_sendRetries)
170 if (m_retryCounter > 60)
171 m_retryCounter -= 60;
172
173 List<int> keys = new List<int>();
174 foreach (int a in m_retryQueue.Keys)
175 { 173 {
176 keys.Add(a); 174 if(m_inRetries)
175 return;
176 m_inRetries = true;
177 } 177 }
178 foreach (int a in keys) 178
179 m_retryCounter++;
180 if(m_retryCounter >= 61 ) // avoid overflow 60 is max in use below
181 m_retryCounter = 1;
182
183 int inUse = 0;
184 int nextlevel;
185 int timefactor;
186 List<AssetBase> retrylist;
187 // we need to go down
188 for(int i = MAXSENDRETRIESLEN - 1; i >= 0; i--)
179 { 189 {
190 lock(m_sendRetries)
191 retrylist = m_sendRetries[i];
192
193 if(retrylist == null)
194 continue;
195
196 inUse++;
197 nextlevel = i + 1;
198
180 //We exponentially fall back on frequency until we reach one attempt per hour 199 //We exponentially fall back on frequency until we reach one attempt per hour
181 //The net result is that we end up in the queue for roughly 24 hours.. 200 //The net result is that we end up in the queue for roughly 24 hours..
182 //24 hours worth of assets could be a lot, so the hope is that the region admin 201 //24 hours worth of assets could be a lot, so the hope is that the region admin
183 //will have gotten the asset connector back online quickly! 202 //will have gotten the asset connector back online quickly!
184 203 if(i == 0)
185 int timefactor = a ^ 2; 204 timefactor = 1;
186 if (timefactor > 60) 205 else
187 { 206 {
188 timefactor = 60; 207 timefactor = 1 << nextlevel;
208 if (timefactor > 60)
209 timefactor = 60;
189 } 210 }
190 211
191 //First, find out if we care about this timefactor 212 if(m_retryCounter < timefactor)
192 if (timefactor % a == 0) 213 continue; // to update inUse;
193 {
194 //Yes, we do!
195 List<AssetBase> retrylist = m_retryQueue[a];
196 m_retryQueue.Remove(a);
197 214
198 foreach(AssetBase ass in retrylist) 215 if (m_retryCounter % timefactor != 0)
199 { 216 continue;
200 Store(ass); //Store my ass. This function will put it back in the dictionary if it fails 217
201 } 218 // a list to retry
202 } 219 lock(m_sendRetries)
220 m_sendRetries[i] = null;
221
222 // we are the only ones with a copy of this retrylist now
223 foreach(AssetBase ass in retrylist)
224 retryStore(ass, nextlevel);
203 } 225 }
204 226
205 if (m_retryQueue.Count == 0) 227 lock(m_sendRetries)
206 { 228 {
207 //It might only be one tick per minute, but I have 229 if(inUse == 0 )
208 //repented and abandoned my wasteful ways 230 m_retryTimer.Stop();
209 m_retryCounter = 0; 231
210 m_retryTimer.Stop(); 232 m_inRetries = false;
211 } 233 }
212 } 234 }
213 235
@@ -237,8 +259,9 @@ namespace OpenSim.Services.Connectors
237 259
238 asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth); 260 asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth);
239 261
240 if (m_Cache != null) 262
241 m_Cache.Cache(asset); 263 if (asset != null && m_Cache != null)
264 m_Cache.Cache(asset);
242 } 265 }
243 return asset; 266 return asset;
244 } 267 }
@@ -340,25 +363,18 @@ namespace OpenSim.Services.Connectors
340 m_AssetHandlers.Remove(id); 363 m_AssetHandlers.Remove(id);
341 } 364 }
342 365
343 Util.FireAndForget(x => 366 if(handlers != null)
367 {
368 Util.FireAndForget(x =>
344 { 369 {
345
346 foreach (AssetRetrievedEx h in handlers) 370 foreach (AssetRetrievedEx h in handlers)
347 { 371 {
348 // Util.FireAndForget(x =>
349 // {
350 try { h.Invoke(a); } 372 try { h.Invoke(a); }
351 catch { } 373 catch { }
352 // });
353 } 374 }
354 375 handlers.Clear();
355 if (handlers != null)
356 handlers.Clear();
357
358 }); 376 });
359 377 }
360// if (handlers != null)
361// handlers.Clear();
362 success = true; 378 success = true;
363 } 379 }
364 } 380 }
@@ -393,29 +409,24 @@ namespace OpenSim.Services.Connectors
393 { 409 {
394 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); }); 410 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
395 411
396// AssetRetrievedEx handlers;
397 List<AssetRetrievedEx> handlers; 412 List<AssetRetrievedEx> handlers;
398 if (m_AssetHandlers.TryGetValue(id, out handlers)) 413 if (m_AssetHandlers.TryGetValue(id, out handlers))
399 { 414 {
400 // Someone else is already loading this asset. It will notify our handler when done. 415 // Someone else is already loading this asset. It will notify our handler when done.
401// handlers += handlerEx;
402 handlers.Add(handlerEx); 416 handlers.Add(handlerEx);
403 return true; 417 return true;
404 } 418 }
405 419
406 // Load the asset ourselves
407// handlers += handlerEx;
408 handlers = new List<AssetRetrievedEx>(); 420 handlers = new List<AssetRetrievedEx>();
409 handlers.Add(handlerEx); 421 handlers.Add(handlerEx);
410 422
411 m_AssetHandlers.Add(id, handlers); 423 m_AssetHandlers.Add(id, handlers);
412 }
413
414 QueuedAssetRequest request = new QueuedAssetRequest();
415 request.id = id;
416 request.uri = uri;
417 424
418 m_requestQueue.Enqueue(request); 425 QueuedAssetRequest request = new QueuedAssetRequest();
426 request.id = id;
427 request.uri = uri;
428 m_requestQueue.Enqueue(request);
429 }
419 } 430 }
420 else 431 else
421 { 432 {
@@ -495,43 +506,34 @@ namespace OpenSim.Services.Connectors
495 newID = SynchronousRestObjectRequester. 506 newID = SynchronousRestObjectRequester.
496 MakeRequest<AssetBase, string>("POST", uri, asset, 100000, m_Auth); 507 MakeRequest<AssetBase, string>("POST", uri, asset, 100000, m_Auth);
497 } 508 }
498 catch {} 509 catch
510 {
511 newID = null;
512 }
499 513
500 if (newID == null || newID == String.Empty || newID == stringUUIDZero) 514 if (newID == null || newID == String.Empty || newID == stringUUIDZero)
501 { 515 {
502 //The asset upload failed, put it in a queue for later 516 //The asset upload failed, try later
503 asset.UploadAttempts++; 517 lock(m_sendRetries)
504 if (asset.UploadAttempts > 30)
505 { 518 {
506 //By this stage we've been in the queue for a good few hours; 519 if (m_sendRetries[0] == null)
507 //We're going to drop the asset. 520 m_sendRetries[0] = new List<AssetBase>();
508 m_log.ErrorFormat("[Assets] Dropping asset {0} - Upload has been in the queue for too long.", asset.ID.ToString()); 521 List<AssetBase> m_queue = m_sendRetries[0];
509 }
510 else
511 {
512 if (!m_retryQueue.ContainsKey(asset.UploadAttempts))
513 {
514 m_retryQueue.Add(asset.UploadAttempts, new List<AssetBase>());
515 }
516 List<AssetBase> m_queue = m_retryQueue[asset.UploadAttempts];
517 m_queue.Add(asset); 522 m_queue.Add(asset);
518 m_log.WarnFormat("[Assets] Upload failed: {0} - Requeuing asset for another run.", asset.ID.ToString()); 523 m_log.WarnFormat("[Assets] Upload failed: {0} type {1} will retry later",
524 asset.ID.ToString(), asset.Type.ToString());
519 m_retryTimer.Start(); 525 m_retryTimer.Start();
520 } 526 }
521 } 527 }
522 else 528 else
523 { 529 {
524 if (asset.UploadAttempts > 0)
525 {
526 m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString());
527 }
528 if (newID != asset.ID) 530 if (newID != asset.ID)
529 { 531 {
530 // Placing this here, so that this work with old asset servers that don't send any reply back 532 // Placing this here, so that this work with old asset servers that don't send any reply back
531 // SynchronousRestObjectRequester returns somethins that is not an empty string 533 // SynchronousRestObjectRequester returns somethins that is not an empty string
532 534
533 asset.ID = newID; 535 asset.ID = newID;
534// what about FullID ???? 536
535 if (m_Cache != null) 537 if (m_Cache != null)
536 m_Cache.Cache(asset); 538 m_Cache.Cache(asset);
537 } 539 }
@@ -539,6 +541,62 @@ namespace OpenSim.Services.Connectors
539 return asset.ID; 541 return asset.ID;
540 } 542 }
541 543
544 public void retryStore(AssetBase asset, int nextRetryLevel)
545 {
546/* this may be bad, so excluding
547 if (m_Cache != null && !m_Cache.Check(asset.ID))
548 {
549 m_log.WarnFormat("[Assets] Upload giveup asset bc no longer in local cache: {0}",
550 asset.ID.ToString();
551 return; // if no longer in cache, it was deleted or expired
552 }
553*/
554 string uri = MapServer(asset.FullID.ToString()) + "/assets/";
555
556 string newID = null;
557 try
558 {
559 newID = SynchronousRestObjectRequester.
560 MakeRequest<AssetBase, string>("POST", uri, asset, 100000, m_Auth);
561 }
562 catch
563 {
564 newID = null;
565 }
566
567 if (newID == null || newID == String.Empty || newID == stringUUIDZero)
568 {
569 if(nextRetryLevel >= MAXSENDRETRIESLEN)
570 m_log.WarnFormat("[Assets] Upload giveup after several retries id: {0} type {1}",
571 asset.ID.ToString(), asset.Type.ToString());
572 else
573 {
574 lock(m_sendRetries)
575 {
576 if (m_sendRetries[nextRetryLevel] == null)
577 {
578 m_sendRetries[nextRetryLevel] = new List<AssetBase>();
579 }
580 List<AssetBase> m_queue = m_sendRetries[nextRetryLevel];
581 m_queue.Add(asset);
582 m_log.WarnFormat("[Assets] Upload failed: {0} type {1} will retry later",
583 asset.ID.ToString(), asset.Type.ToString());
584 }
585 }
586 }
587 else
588 {
589 m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), nextRetryLevel.ToString());
590 if (newID != asset.ID)
591 {
592 asset.ID = newID;
593
594 if (m_Cache != null)
595 m_Cache.Cache(asset);
596 }
597 }
598 }
599
542 public bool UpdateContent(string id, byte[] data) 600 public bool UpdateContent(string id, byte[] data)
543 { 601 {
544 AssetBase asset = null; 602 AssetBase asset = null;
@@ -569,6 +627,7 @@ namespace OpenSim.Services.Connectors
569 return false; 627 return false;
570 } 628 }
571 629
630
572 public bool Delete(string id) 631 public bool Delete(string id)
573 { 632 {
574 string uri = MapServer(id) + "/assets/" + id; 633 string uri = MapServer(id) + "/assets/" + id;
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index 2340998..aad3bd2 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -159,8 +159,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
159 string filename = string.Empty; 159 string filename = string.Empty;
160 160
161 try 161 try
162 { 162 {
163 WebClient c = new WebClient();
164 //m_log.Debug("JPEG: " + imageURL); 163 //m_log.Debug("JPEG: " + imageURL);
165 string name = regionID.ToString(); 164 string name = regionID.ToString();
166 filename = Path.Combine(storagePath, name + ".jpg"); 165 filename = Path.Combine(storagePath, name + ".jpg");
@@ -168,7 +167,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
168 if (!File.Exists(filename)) 167 if (!File.Exists(filename))
169 { 168 {
170 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: downloading..."); 169 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: downloading...");
171 c.DownloadFile(imageURL, filename); 170 using(WebClient c = new WebClient())
171 c.DownloadFile(imageURL, filename);
172 } 172 }
173 else 173 else
174 { 174 {
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index 3a0d197..8e1bf37 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -106,17 +106,18 @@ namespace OpenSim.Services.Connectors.Simulation
106 106
107 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string myipaddress, out string reason) 107 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string myipaddress, out string reason)
108 { 108 {
109 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
110 reason = String.Empty; 109 reason = String.Empty;
111 myipaddress = String.Empty; 110 myipaddress = String.Empty;
112 111
113 if (destination == null) 112 if (destination == null)
114 { 113 {
115 reason = "Destination not found"; 114 reason = "Destination not found";
116 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null"); 115 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Create agent destination is null");
117 return false; 116 return false;
118 } 117 }
119 118
119 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
120
120 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; 121 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
121 122
122 try 123 try
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 6681f1a..92b3137 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -512,8 +512,8 @@ namespace OpenSim.Services.LLLoginService
512 // 512 //
513 if (m_MessageUrl != String.Empty) 513 if (m_MessageUrl != String.Empty)
514 { 514 {
515 WebClient client = new WebClient(); 515 using(WebClient client = new WebClient())
516 processedMessage = client.DownloadString(m_MessageUrl); 516 processedMessage = client.DownloadString(m_MessageUrl);
517 } 517 }
518 else 518 else
519 { 519 {
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index 668fe53..706d475 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Services.UserAccountService
92 m_RootInstance = this; 92 m_RootInstance = this;
93 MainConsole.Instance.Commands.AddCommand("Users", false, 93 MainConsole.Instance.Commands.AddCommand("Users", false,
94 "create user", 94 "create user",
95 "create user [<first> [<last> [<pass> [<email> [<user id>]]]]]", 95 "create user [<first> [<last> [<pass> [<email> [<user id> [<model>]]]]]]",
96 "Create a new user", HandleCreateUser); 96 "Create a new user", HandleCreateUser);
97 97
98 MainConsole.Instance.Commands.AddCommand("Users", false, 98 MainConsole.Instance.Commands.AddCommand("Users", false,
@@ -353,7 +353,7 @@ namespace OpenSim.Services.UserAccountService
353 /// <summary> 353 /// <summary>
354 /// Handle the create user command from the console. 354 /// Handle the create user command from the console.
355 /// </summary> 355 /// </summary>
356 /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email</param> 356 /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email, userID, model name </param>
357 protected void HandleCreateUser(string module, string[] cmdparams) 357 protected void HandleCreateUser(string module, string[] cmdparams)
358 { 358 {
359 string firstName; 359 string firstName;
@@ -361,6 +361,7 @@ namespace OpenSim.Services.UserAccountService
361 string password; 361 string password;
362 string email; 362 string email;
363 string rawPrincipalId; 363 string rawPrincipalId;
364 string model;
364 365
365 List<char> excluded = new List<char>(new char[]{' '}); 366 List<char> excluded = new List<char>(new char[]{' '});
366 367
@@ -385,11 +386,16 @@ namespace OpenSim.Services.UserAccountService
385 else 386 else
386 rawPrincipalId = cmdparams[6]; 387 rawPrincipalId = cmdparams[6];
387 388
389 if (cmdparams.Length < 8)
390 model = MainConsole.Instance.CmdPrompt("Model name","");
391 else
392 model = cmdparams[7];
393
388 UUID principalId = UUID.Zero; 394 UUID principalId = UUID.Zero;
389 if (!UUID.TryParse(rawPrincipalId, out principalId)) 395 if (!UUID.TryParse(rawPrincipalId, out principalId))
390 throw new Exception(string.Format("ID {0} is not a valid UUID", rawPrincipalId)); 396 throw new Exception(string.Format("ID {0} is not a valid UUID", rawPrincipalId));
391 397
392 CreateUser(UUID.Zero, principalId, firstName, lastName, password, email); 398 CreateUser(UUID.Zero, principalId, firstName, lastName, password, email, model);
393 } 399 }
394 400
395 protected void HandleShowAccount(string module, string[] cmdparams) 401 protected void HandleShowAccount(string module, string[] cmdparams)
@@ -544,7 +550,8 @@ namespace OpenSim.Services.UserAccountService
544 /// <param name="lastName"></param> 550 /// <param name="lastName"></param>
545 /// <param name="password"></param> 551 /// <param name="password"></param>
546 /// <param name="email"></param> 552 /// <param name="email"></param>
547 public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email) 553 /// <param name="model"></param>
554 public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email, string model = "")
548 { 555 {
549 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); 556 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
550 if (null == account) 557 if (null == account)
@@ -603,7 +610,12 @@ namespace OpenSim.Services.UserAccountService
603 } 610 }
604 611
605 if (m_CreateDefaultAvatarEntries) 612 if (m_CreateDefaultAvatarEntries)
606 CreateDefaultAppearanceEntries(account.PrincipalID); 613 {
614 if (String.IsNullOrEmpty(model))
615 CreateDefaultAppearanceEntries(account.PrincipalID);
616 else
617 EstablishAppearance(account.PrincipalID, model);
618 }
607 } 619 }
608 620
609 m_log.InfoFormat( 621 m_log.InfoFormat(
@@ -734,6 +746,7 @@ namespace OpenSim.Services.UserAccountService
734 wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID); 746 wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID);
735 747
736 AvatarAppearance ap = new AvatarAppearance(); 748 AvatarAppearance ap = new AvatarAppearance();
749 // this loop works, but is questionable
737 for (int i = 0; i < 6; i++) 750 for (int i = 0; i < 6; i++)
738 { 751 {
739 ap.SetWearable(i, wearables[i]); 752 ap.SetWearable(i, wearables[i]);
@@ -742,5 +755,205 @@ namespace OpenSim.Services.UserAccountService
742 m_AvatarService.SetAppearance(principalID, ap); 755 m_AvatarService.SetAppearance(principalID, ap);
743 } 756 }
744 } 757 }
758
759 protected void EstablishAppearance(UUID destinationAgent, string model)
760 {
761 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Establishing new appearance for {0} - {1}",
762 destinationAgent.ToString(), model);
763
764 string[] modelSpecifiers = model.Split();
765 if (modelSpecifiers.Length != 2)
766 {
767 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Invalid model name \'{0}\'. Falling back to Ruth for {1}",
768 model, destinationAgent);
769 CreateDefaultAppearanceEntries(destinationAgent);
770 return;
771 }
772
773 // Does the source model exist?
774 UserAccount modelAccount = GetUserAccount(UUID.Zero, modelSpecifiers[0], modelSpecifiers[1]);
775 if (modelAccount == null)
776 {
777 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Requested model \'{0}\' not found. Falling back to Ruth for {1}",
778 model, destinationAgent);
779 CreateDefaultAppearanceEntries(destinationAgent);
780 return;
781 }
782
783 // Does the source model have an established appearance herself?
784 AvatarAppearance modelAppearance = m_AvatarService.GetAppearance(modelAccount.PrincipalID);
785 if (modelAppearance == null)
786 {
787 m_log.WarnFormat("USER ACCOUNT SERVICE]: Requested model \'{0}\' does not have an established appearance. Falling back to Ruth for {1}",
788 model, destinationAgent);
789 CreateDefaultAppearanceEntries(destinationAgent);
790 return;
791 }
792
793 try
794 {
795 CopyWearablesAndAttachments(destinationAgent, modelAccount.PrincipalID, modelAppearance);
796
797 m_AvatarService.SetAppearance(destinationAgent, modelAppearance);
798 }
799 catch (Exception e)
800 {
801 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring appearance for {0} : {1}",
802 destinationAgent, e.Message);
803 }
804
805 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Finished establishing appearance for {0}",
806 destinationAgent.ToString());
807 }
808
809 /// <summary>
810 /// This method is called by EstablishAppearance to do a copy all inventory items
811 /// worn or attached to the Clothing inventory folder of the receiving avatar.
812 /// In parallel the avatar wearables and attachments are updated.
813 /// </summary>
814 private void CopyWearablesAndAttachments(UUID destination, UUID source, AvatarAppearance avatarAppearance)
815 {
816 // Get Clothing folder of receiver
817 InventoryFolderBase destinationFolder = m_InventoryService.GetFolderForType(destination, FolderType.Clothing);
818
819 if (destinationFolder == null)
820 throw new Exception("Cannot locate folder(s)");
821
822 // Missing destination folder? This should *never* be the case
823 if (destinationFolder.Type != (short)FolderType.Clothing)
824 {
825 destinationFolder = new InventoryFolderBase();
826
827 destinationFolder.ID = UUID.Random();
828 destinationFolder.Name = "Clothing";
829 destinationFolder.Owner = destination;
830 destinationFolder.Type = (short)AssetType.Clothing;
831 destinationFolder.ParentID = m_InventoryService.GetRootFolder(destination).ID;
832 destinationFolder.Version = 1;
833 m_InventoryService.AddFolder(destinationFolder); // store base record
834 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Created folder for destination {0}", source);
835 }
836
837 // Wearables
838 AvatarWearable[] wearables = avatarAppearance.Wearables;
839 AvatarWearable wearable;
840
841 for (int i = 0; i < wearables.Length; i++)
842 {
843 wearable = wearables[i];
844 if (wearable[0].ItemID != UUID.Zero)
845 {
846 // Get inventory item and copy it
847 InventoryItemBase item = m_InventoryService.GetItem(source, wearable[0].ItemID);
848
849 if (item != null)
850 {
851 InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination);
852 destinationItem.Name = item.Name;
853 destinationItem.Owner = destination;
854 destinationItem.Description = item.Description;
855 destinationItem.InvType = item.InvType;
856 destinationItem.CreatorId = item.CreatorId;
857 destinationItem.CreatorData = item.CreatorData;
858 destinationItem.NextPermissions = item.NextPermissions;
859 destinationItem.CurrentPermissions = item.CurrentPermissions;
860 destinationItem.BasePermissions = item.BasePermissions;
861 destinationItem.EveryOnePermissions = item.EveryOnePermissions;
862 destinationItem.GroupPermissions = item.GroupPermissions;
863 destinationItem.AssetType = item.AssetType;
864 destinationItem.AssetID = item.AssetID;
865 destinationItem.GroupID = item.GroupID;
866 destinationItem.GroupOwned = item.GroupOwned;
867 destinationItem.SalePrice = item.SalePrice;
868 destinationItem.SaleType = item.SaleType;
869 destinationItem.Flags = item.Flags;
870 destinationItem.CreationDate = item.CreationDate;
871 destinationItem.Folder = destinationFolder.ID;
872 ApplyNextOwnerPermissions(destinationItem);
873
874 m_InventoryService.AddItem(destinationItem);
875 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID);
876
877 // Wear item
878 AvatarWearable newWearable = new AvatarWearable();
879 newWearable.Wear(destinationItem.ID, wearable[0].AssetID);
880 avatarAppearance.SetWearable(i, newWearable);
881 }
882 else
883 {
884 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring {0} to folder {1}", wearable[0].ItemID, destinationFolder.ID);
885 }
886 }
887 }
888
889 // Attachments
890 List<AvatarAttachment> attachments = avatarAppearance.GetAttachments();
891
892 foreach (AvatarAttachment attachment in attachments)
893 {
894 int attachpoint = attachment.AttachPoint;
895 UUID itemID = attachment.ItemID;
896
897 if (itemID != UUID.Zero)
898 {
899 // Get inventory item and copy it
900 InventoryItemBase item = m_InventoryService.GetItem(source, itemID);
901
902 if (item != null)
903 {
904 InventoryItemBase destinationItem = new InventoryItemBase(UUID.Random(), destination);
905 destinationItem.Name = item.Name;
906 destinationItem.Owner = destination;
907 destinationItem.Description = item.Description;
908 destinationItem.InvType = item.InvType;
909 destinationItem.CreatorId = item.CreatorId;
910 destinationItem.CreatorData = item.CreatorData;
911 destinationItem.NextPermissions = item.NextPermissions;
912 destinationItem.CurrentPermissions = item.CurrentPermissions;
913 destinationItem.BasePermissions = item.BasePermissions;
914 destinationItem.EveryOnePermissions = item.EveryOnePermissions;
915 destinationItem.GroupPermissions = item.GroupPermissions;
916 destinationItem.AssetType = item.AssetType;
917 destinationItem.AssetID = item.AssetID;
918 destinationItem.GroupID = item.GroupID;
919 destinationItem.GroupOwned = item.GroupOwned;
920 destinationItem.SalePrice = item.SalePrice;
921 destinationItem.SaleType = item.SaleType;
922 destinationItem.Flags = item.Flags;
923 destinationItem.CreationDate = item.CreationDate;
924 destinationItem.Folder = destinationFolder.ID;
925 ApplyNextOwnerPermissions(destinationItem);
926
927 m_InventoryService.AddItem(destinationItem);
928 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Added item {0} to folder {1}", destinationItem.ID, destinationFolder.ID);
929
930 // Attach item
931 avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID);
932 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Attached {0}", destinationItem.ID);
933 }
934 else
935 {
936 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Error transferring {0} to folder {1}", itemID, destinationFolder.ID);
937 }
938 }
939 }
940 }
941
942 /// <summary>
943 /// Apply next owner permissions.
944 /// </summary>
945 private void ApplyNextOwnerPermissions(InventoryItemBase item)
946 {
947 if (item.InvType == (int)InventoryType.Object)
948 {
949 uint perms = item.CurrentPermissions;
950 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms);
951 item.CurrentPermissions = perms;
952 }
953
954 item.CurrentPermissions &= item.NextPermissions;
955 item.BasePermissions &= item.NextPermissions;
956 item.EveryOnePermissions &= item.NextPermissions;
957 }
745 } 958 }
746} 959}