aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
authorteravus2012-11-15 10:05:16 -0500
committerteravus2012-11-15 10:05:16 -0500
commite9153e1d1aae50024d8cd05fe14a9bce34343a0e (patch)
treebc111d34f95a26b99c7e34d9e495dc14d1802cc3 /OpenSim/Region/CoreModules
parentMerge master into teravuswork (diff)
downloadopensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.zip
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.gz
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.bz2
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.xz
Revert "Merge master into teravuswork", it should have been avination, not master.
This reverts commit dfac269032300872c4d0dc507f4f9062d102b0f4, reversing changes made to 619c39e5144f15aca129d6d999bcc5c34133ee64.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs138
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs222
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs39
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs26
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs68
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs196
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs76
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs224
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs79
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs (renamed from OpenSim/Region/ScriptEngine/Shared/ScriptException.cs)33
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs4
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs331
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml1
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs277
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs49
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs281
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs159
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs133
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs136
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs10
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs19
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs46
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs434
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs634
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs153
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs438
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs404
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs110
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs522
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs313
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs7
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs (renamed from OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs)81
62 files changed, 1778 insertions, 4763 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..8a4fd8f 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -57,36 +57,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
57 } 57 }
58 58
59 /// <summary> 59 /// <summary>
60 /// Return the xfer uploader for the given transaction. 60 /// Return a xfer uploader if one does not already exist.
61 /// </summary> 61 /// </summary>
62 /// <remarks>
63 /// If an uploader does not already exist for this transaction then it is created, otherwise the existing
64 /// uploader is returned.
65 /// </remarks>
66 /// <param name="transactionID"></param> 62 /// <param name="transactionID"></param>
67 /// <returns>The asset xfer uploader</returns> 63 /// <param name="assetID">
68 public AssetXferUploader RequestXferUploader(UUID transactionID) 64 /// We must transfer the new asset ID into the uploader on creation, otherwise
65 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
66 /// asset id.
67 /// </param>
68 /// <returns>
69 /// The xfer uploader requested. Null if one is already in existence.
70 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
71 /// transfers are made. Needs to be corrected.
72 /// </returns>
73 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
69 { 74 {
70 AssetXferUploader uploader;
71
72 lock (XferUploaders) 75 lock (XferUploaders)
73 { 76 {
74 if (!XferUploaders.ContainsKey(transactionID)) 77 if (!XferUploaders.ContainsKey(transactionID))
75 { 78 {
76 uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); 79 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile);
77 80
78// m_log.DebugFormat( 81// m_log.DebugFormat(
79// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); 82// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
80 83
81 XferUploaders.Add(transactionID, uploader); 84 XferUploaders.Add(transactionID, uploader);
82 } 85
83 else 86 return uploader;
84 {
85 uploader = XferUploaders[transactionID];
86 } 87 }
87 } 88 }
88 89
89 return uploader; 90 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
91
92 return null;
90 } 93 }
91 94
92 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 95 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
@@ -148,30 +151,117 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
148 string description, string name, sbyte invType, 151 string description, string name, sbyte invType,
149 sbyte type, byte wearableType, uint nextOwnerMask) 152 sbyte type, byte wearableType, uint nextOwnerMask)
150 { 153 {
151 AssetXferUploader uploader = RequestXferUploader(transactionID); 154 AssetXferUploader uploader = null;
155
156 lock (XferUploaders)
157 {
158 if (XferUploaders.ContainsKey(transactionID))
159 uploader = XferUploaders[transactionID];
160 }
152 161
153 uploader.RequestCreateInventoryItem( 162 if (uploader != null)
154 remoteClient, folderID, callbackID, 163 {
155 description, name, invType, type, wearableType, nextOwnerMask); 164 uploader.RequestCreateInventoryItem(
165 remoteClient, transactionID, folderID,
166 callbackID, description, name, invType, type,
167 wearableType, nextOwnerMask);
156 168
157 return true; 169 return true;
170 }
171
172 return false;
173 }
174
175 /// <summary>
176 /// Get an uploaded asset. If the data is successfully retrieved,
177 /// the transaction will be removed.
178 /// </summary>
179 /// <param name="transactionID"></param>
180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
181 private AssetBase GetTransactionAsset(UUID transactionID)
182 {
183 lock (XferUploaders)
184 {
185 if (XferUploaders.ContainsKey(transactionID))
186 {
187 AssetXferUploader uploader = XferUploaders[transactionID];
188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
190
191 return asset;
192 }
193 }
194
195 return null;
158 } 196 }
159 197
160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 198 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
161 SceneObjectPart part, UUID transactionID, 199 SceneObjectPart part, UUID transactionID,
162 TaskInventoryItem item) 200 TaskInventoryItem item)
163 { 201 {
164 AssetXferUploader uploader = RequestXferUploader(transactionID); 202 AssetXferUploader uploader = null;
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
211 {
212 AssetBase asset = GetTransactionAsset(transactionID);
213
214 // Only legacy viewers use this, and they prefer CAPS, which
215 // we have, so this really never runs.
216 // Allow it, but only for "safe" types.
217 if ((InventoryType)item.InvType != InventoryType.Notecard &&
218 (InventoryType)item.InvType != InventoryType.LSL)
219 return;
165 220
166 uploader.RequestUpdateTaskInventoryItem(remoteClient, item); 221 if (asset != null)
222 {
223// m_log.DebugFormat(
224// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
225// item.Name, part.Name, transactionID);
226
227 asset.FullID = UUID.Random();
228 asset.Name = item.Name;
229 asset.Description = item.Description;
230 asset.Type = (sbyte)item.Type;
231 item.AssetID = asset.FullID;
232
233 m_Scene.AssetService.Store(asset);
234 }
235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
167 } 242 }
168 243
169 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 244 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
170 UUID transactionID, InventoryItemBase item) 245 UUID transactionID, InventoryItemBase item)
171 { 246 {
172 AssetXferUploader uploader = RequestXferUploader(transactionID); 247 AssetXferUploader uploader = null;
248
249 lock (XferUploaders)
250 {
251 if (XferUploaders.ContainsKey(transactionID))
252 uploader = XferUploaders[transactionID];
253 }
173 254
174 uploader.RequestUpdateInventoryItem(remoteClient, item); 255 if (uploader != null)
256 {
257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
264 }
175 } 265 }
176 } 266 }
177} 267}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 4bb8986..441c4ff 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) 215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 { 216 {
217 m_log.DebugFormat( 217 m_log.DebugFormat(
218 "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", 218 "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); 219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
220 220
221 AgentAssetTransactions transactions = 221 AgentAssetTransactions transactions =
@@ -274,8 +274,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
274 } 274 }
275 275
276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction); 277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID);
278 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); 278
279 if (uploader != null)
280 {
281 uploader.Initialise(remoteClient, assetID, transaction, type,
282 data, storeLocal, tempFile);
283 }
279 } 284 }
280 285
281 /// <summary> 286 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index f6dd5af..4cedfe6 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -49,75 +49,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 /// <summary> 51 /// <summary>
52 /// Upload state.
53 /// </summary>
54 /// <remarks>
55 /// New -> Uploading -> Complete
56 /// </remarks>
57 private enum UploadState
58 {
59 New,
60 Uploading,
61 Complete
62 }
63
64 /// <summary>
65 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 52 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
66 /// are performing a delayed update. 53 /// are performing a delayed update.
67 /// </summary> 54 /// </summary>
68 AgentAssetTransactions m_transactions; 55 AgentAssetTransactions m_transactions;
69 56
70 private UploadState m_uploadState = UploadState.New;
71
72 private AssetBase m_asset; 57 private AssetBase m_asset;
73 private UUID InventFolder = UUID.Zero; 58 private UUID InventFolder = UUID.Zero;
74 private sbyte invType = 0; 59 private sbyte invType = 0;
75 60
76 private bool m_createItem; 61 private bool m_createItem = false;
77 private uint m_createItemCallback; 62 private uint m_createItemCallback = 0;
78 63 private bool m_updateItem = false;
79 private bool m_updateItem;
80 private InventoryItemBase m_updateItemData; 64 private InventoryItemBase m_updateItemData;
81 65
82 private bool m_updateTaskItem;
83 private TaskInventoryItem m_updateTaskItemData;
84
85 private string m_description = String.Empty; 66 private string m_description = String.Empty;
86 private bool m_dumpAssetToFile; 67 private bool m_dumpAssetToFile;
68 private bool m_finished = false;
87 private string m_name = String.Empty; 69 private string m_name = String.Empty;
88// private bool m_storeLocal; 70 private bool m_storeLocal;
89 private uint nextPerm = 0; 71 private uint nextPerm = 0;
90 private IClientAPI ourClient; 72 private IClientAPI ourClient;
91 73 private UUID TransactionID = UUID.Zero;
92 private UUID m_transactionID;
93
94 private sbyte type = 0; 74 private sbyte type = 0;
95 private byte wearableType = 0; 75 private byte wearableType = 0;
96 private byte[] m_oldData = null; 76 private byte[] m_oldData = null;
97 public ulong XferID; 77 public ulong XferID;
98 private Scene m_Scene; 78 private Scene m_Scene;
99 79
100 /// <summary> 80 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile)
101 /// AssetXferUploader constructor
102 /// </summary>
103 /// <param name='transactions'>/param>
104 /// <param name='scene'></param>
105 /// <param name='transactionID'></param>
106 /// <param name='dumpAssetToFile'>
107 /// If true then when the asset is uploaded it is dumped to a file with the format
108 /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
109 /// now.Year, now.Month, now.Day, now.Hour, now.Minute,
110 /// now.Second, m_asset.Name, m_asset.Type);
111 /// for debugging purposes.
112 /// </param>
113 public AssetXferUploader(
114 AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile)
115 { 81 {
116 m_asset = new AssetBase();
117
118 m_transactions = transactions; 82 m_transactions = transactions;
119 m_transactionID = transactionID;
120 m_Scene = scene; 83 m_Scene = scene;
84 m_asset = new AssetBase() { FullID = assetID };
121 m_dumpAssetToFile = dumpAssetToFile; 85 m_dumpAssetToFile = dumpAssetToFile;
122 } 86 }
123 87
@@ -163,50 +127,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
163 } 127 }
164 128
165 /// <summary> 129 /// <summary>
166 /// Start asset transfer from the client 130 /// Initialise asset transfer from the client
167 /// </summary> 131 /// </summary>
168 /// <param name="remoteClient"></param> 132 /// <param name="xferID"></param>
169 /// <param name="assetID"></param> 133 /// <param name="packetID"></param>
170 /// <param name="transaction"></param> 134 /// <param name="data"></param>
171 /// <param name="type"></param> 135 public void Initialise(IClientAPI remoteClient, UUID assetID,
172 /// <param name="data"> 136 UUID transaction, sbyte type, byte[] data, bool storeLocal,
173 /// Optional data. If present then the asset is created immediately with this data 137 bool tempFile)
174 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
175 /// </param>
176 /// <param name="storeLocal"></param>
177 /// <param name="tempFile"></param>
178 public void StartUpload(
179 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
180 bool tempFile)
181 { 138 {
182// m_log.DebugFormat( 139// m_log.DebugFormat(
183// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", 140// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
184// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); 141// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
185 142
186 lock (this)
187 {
188 if (m_uploadState != UploadState.New)
189 {
190 m_log.WarnFormat(
191 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
192 assetID, transaction, remoteClient.Name, m_uploadState);
193
194 return;
195 }
196
197 m_uploadState = UploadState.Uploading;
198 }
199
200 ourClient = remoteClient; 143 ourClient = remoteClient;
201 144 m_asset.Name = "blank";
202 m_asset.FullID = assetID; 145 m_asset.Description = "empty";
203 m_asset.Type = type; 146 m_asset.Type = type;
204 m_asset.CreatorID = remoteClient.AgentId.ToString(); 147 m_asset.CreatorID = remoteClient.AgentId.ToString();
205 m_asset.Data = data; 148 m_asset.Data = data;
206 m_asset.Local = storeLocal; 149 m_asset.Local = storeLocal;
207 m_asset.Temporary = tempFile; 150 m_asset.Temporary = tempFile;
208 151
209// m_storeLocal = storeLocal; 152 TransactionID = transaction;
153 m_storeLocal = storeLocal;
210 154
211 if (m_asset.Data.Length > 2) 155 if (m_asset.Data.Length > 2)
212 { 156 {
@@ -231,35 +175,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
231 175
232 protected void SendCompleteMessage() 176 protected void SendCompleteMessage()
233 { 177 {
178 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
179 m_asset.FullID);
180
234 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 181 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
235 // message from other client UDP. 182 // message from other client UDP.
236 lock (this) 183 lock (this)
237 { 184 {
238 m_uploadState = UploadState.Complete; 185 m_finished = true;
239
240 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
241
242 if (m_createItem) 186 if (m_createItem)
243 { 187 {
244 CompleteCreateItem(m_createItemCallback); 188 DoCreateItem(m_createItemCallback);
245 } 189 }
246 else if (m_updateItem) 190 else if (m_updateItem)
247 { 191 {
248 CompleteItemUpdate(m_updateItemData); 192 StoreAssetForItemUpdate(m_updateItemData);
193
194 // Remove ourselves from the list of transactions if completion was delayed until the transaction
195 // was complete.
196 // TODO: Should probably do the same for create item.
197 m_transactions.RemoveXferUploader(TransactionID);
249 } 198 }
250 else if (m_updateTaskItem) 199 else if (m_storeLocal)
251 { 200 {
252 CompleteTaskItemUpdate(m_updateTaskItemData); 201 m_Scene.AssetService.Store(m_asset);
253 } 202 }
254// else if (m_storeLocal)
255// {
256// m_Scene.AssetService.Store(m_asset);
257// }
258 } 203 }
259 204
260 m_log.DebugFormat( 205 m_log.DebugFormat(
261 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", 206 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
262 m_asset.FullID, m_transactionID); 207 m_asset.FullID, TransactionID);
263 208
264 if (m_dumpAssetToFile) 209 if (m_dumpAssetToFile)
265 { 210 {
@@ -287,37 +232,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
287 } 232 }
288 233
289 public void RequestCreateInventoryItem(IClientAPI remoteClient, 234 public void RequestCreateInventoryItem(IClientAPI remoteClient,
290 UUID folderID, uint callbackID, 235 UUID transactionID, UUID folderID, uint callbackID,
291 string description, string name, sbyte invType, 236 string description, string name, sbyte invType,
292 sbyte type, byte wearableType, uint nextOwnerMask) 237 sbyte type, byte wearableType, uint nextOwnerMask)
293 { 238 {
294 InventFolder = folderID; 239 if (TransactionID == transactionID)
295 m_name = name;
296 m_description = description;
297 this.type = type;
298 this.invType = invType;
299 this.wearableType = wearableType;
300 nextPerm = nextOwnerMask;
301 m_asset.Name = name;
302 m_asset.Description = description;
303 m_asset.Type = type;
304
305 // We must lock to avoid a race with a separate thread uploading the asset.
306 lock (this)
307 { 240 {
308 if (m_uploadState == UploadState.Complete) 241 InventFolder = folderID;
242 m_name = name;
243 m_description = description;
244 this.type = type;
245 this.invType = invType;
246 this.wearableType = wearableType;
247 nextPerm = nextOwnerMask;
248 m_asset.Name = name;
249 m_asset.Description = description;
250 m_asset.Type = type;
251
252 // We must lock to avoid a race with a separate thread uploading the asset.
253 lock (this)
309 { 254 {
310 CompleteCreateItem(callbackID); 255 if (m_finished)
311 } 256 {
312 else 257 DoCreateItem(callbackID);
313 { 258 }
314 m_createItem = true; //set flag so the inventory item is created when upload is complete 259 else
315 m_createItemCallback = callbackID; 260 {
261 m_createItem = true; //set flag so the inventory item is created when upload is complete
262 m_createItemCallback = callbackID;
263 }
316 } 264 }
317 } 265 }
318 } 266 }
319 267
320 public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) 268 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item)
321 { 269 {
322 // We must lock to avoid a race with a separate thread uploading the asset. 270 // We must lock to avoid a race with a separate thread uploading the asset.
323 lock (this) 271 lock (this)
@@ -332,9 +280,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
332 item.AssetID = m_asset.FullID; 280 item.AssetID = m_asset.FullID;
333 m_Scene.InventoryService.UpdateItem(item); 281 m_Scene.InventoryService.UpdateItem(item);
334 282
335 if (m_uploadState == UploadState.Complete) 283 if (m_finished)
336 { 284 {
337 CompleteItemUpdate(item); 285 StoreAssetForItemUpdate(item);
338 } 286 }
339 else 287 else
340 { 288 {
@@ -348,59 +296,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
348 } 296 }
349 } 297 }
350 298
351 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem)
352 {
353 // We must lock to avoid a race with a separate thread uploading the asset.
354 lock (this)
355 {
356 m_asset.Name = taskItem.Name;
357 m_asset.Description = taskItem.Description;
358 m_asset.Type = (sbyte)taskItem.Type;
359 taskItem.AssetID = m_asset.FullID;
360
361 if (m_uploadState == UploadState.Complete)
362 {
363 CompleteTaskItemUpdate(taskItem);
364 }
365 else
366 {
367 m_updateTaskItem = true;
368 m_updateTaskItemData = taskItem;
369 }
370 }
371 }
372
373 /// <summary> 299 /// <summary>
374 /// Store the asset for the given item when it has been uploaded. 300 /// Store the asset for the given item.
375 /// </summary> 301 /// </summary>
376 /// <param name="item"></param> 302 /// <param name="item"></param>
377 private void CompleteItemUpdate(InventoryItemBase item) 303 private void StoreAssetForItemUpdate(InventoryItemBase item)
378 { 304 {
379// m_log.DebugFormat( 305// m_log.DebugFormat(
380// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 306// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
381// m_asset.FullID, item.Name, ourClient.Name); 307// m_asset.FullID, item.Name, ourClient.Name);
382 308
383 m_Scene.AssetService.Store(m_asset); 309 m_Scene.AssetService.Store(m_asset);
384
385 m_transactions.RemoveXferUploader(m_transactionID);
386 }
387
388 /// <summary>
389 /// Store the asset for the given task item when it has been uploaded.
390 /// </summary>
391 /// <param name="taskItem"></param>
392 private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
393 {
394// m_log.DebugFormat(
395// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
396// m_asset.FullID, taskItem.Name, ourClient.Name);
397
398 m_Scene.AssetService.Store(m_asset);
399
400 m_transactions.RemoveXferUploader(m_transactionID);
401 } 310 }
402 311
403 private void CompleteCreateItem(uint callbackID) 312 private void DoCreateItem(uint callbackID)
404 { 313 {
405 ValidateAssets(); 314 ValidateAssets();
406 m_Scene.AssetService.Store(m_asset); 315 m_Scene.AssetService.Store(m_asset);
@@ -430,8 +339,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
430 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 339 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
431 else 340 else
432 ourClient.SendAlertMessage("Unable to create inventory item"); 341 ourClient.SendAlertMessage("Unable to create inventory item");
433
434 m_transactions.RemoveXferUploader(m_transactionID);
435 } 342 }
436 343
437 private void ValidateAssets() 344 private void ValidateAssets()
@@ -509,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
509 /// <returns>null if the asset has not finished uploading</returns> 416 /// <returns>null if the asset has not finished uploading</returns>
510 public AssetBase GetAssetData() 417 public AssetBase GetAssetData()
511 { 418 {
512 if (m_uploadState == UploadState.Complete) 419 if (m_finished)
513 { 420 {
514 ValidateAssets(); 421 ValidateAssets();
515 return m_asset; 422 return m_asset;
@@ -562,3 +469,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
562 } 469 }
563 } 470 }
564} 471}
472
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d1a563c..7d7176f 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces;
52[assembly: Addin("FlotsamAssetCache", "1.1")] 52[assembly: Addin("FlotsamAssetCache", "1.1")]
53[assembly: AddinDependency("OpenSim", "0.5")] 53[assembly: AddinDependency("OpenSim", "0.5")]
54 54
55namespace OpenSim.Region.CoreModules.Asset 55namespace Flotsam.RegionModules.AssetCache
56{ 56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService 58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
@@ -107,6 +107,8 @@ namespace OpenSim.Region.CoreModules.Asset
107 private IAssetService m_AssetService; 107 private IAssetService m_AssetService;
108 private List<Scene> m_Scenes = new List<Scene>(); 108 private List<Scene> m_Scenes = new List<Scene>();
109 109
110 private bool m_DeepScanBeforePurge;
111
110 public FlotsamAssetCache() 112 public FlotsamAssetCache()
111 { 113 {
112 m_InvalidChars.AddRange(Path.GetInvalidPathChars()); 114 m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@@ -168,6 +170,8 @@ namespace OpenSim.Region.CoreModules.Asset
168 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); 170 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
169 171
170 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); 172 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
173
174 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
171 } 175 }
172 176
173 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
@@ -515,10 +519,13 @@ namespace OpenSim.Region.CoreModules.Asset
515 // Purge all files last accessed prior to this point 519 // Purge all files last accessed prior to this point
516 DateTime purgeLine = DateTime.Now - m_FileExpiration; 520 DateTime purgeLine = DateTime.Now - m_FileExpiration;
517 521
518 // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, 522 // An optional deep scan at this point will ensure assets present in scenes,
519 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain 523 // or referenced by objects in the scene, but not recently accessed
520 // such local assets if they have not been recently accessed. 524 // are not purged.
521 TouchAllSceneAssets(false); 525 if (m_DeepScanBeforePurge)
526 {
527 CacheScenes();
528 }
522 529
523 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 530 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
524 { 531 {
@@ -711,14 +718,11 @@ namespace OpenSim.Region.CoreModules.Asset
711 718
712 /// <summary> 719 /// <summary>
713 /// Iterates through all Scenes, doing a deep scan through assets 720 /// Iterates through all Scenes, doing a deep scan through assets
714 /// to update the access time of all assets present in the scene or referenced by assets 721 /// to cache all assets present in the scene or referenced by assets
715 /// in the scene. 722 /// in the scene
716 /// </summary> 723 /// </summary>
717 /// <param name="storeUncached"> 724 /// <returns></returns>
718 /// If true, then assets scanned which are not found in cache are added to the cache. 725 private int CacheScenes()
719 /// </param>
720 /// <returns>Number of distinct asset references found in the scene.</returns>
721 private int TouchAllSceneAssets(bool storeUncached)
722 { 726 {
723 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 727 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
724 728
@@ -741,7 +745,7 @@ namespace OpenSim.Region.CoreModules.Asset
741 { 745 {
742 File.SetLastAccessTime(filename, DateTime.Now); 746 File.SetLastAccessTime(filename, DateTime.Now);
743 } 747 }
744 else if (storeUncached) 748 else
745 { 749 {
746 m_AssetService.Get(assetID.ToString()); 750 m_AssetService.Get(assetID.ToString());
747 } 751 }
@@ -869,14 +873,13 @@ namespace OpenSim.Region.CoreModules.Asset
869 873
870 break; 874 break;
871 875
876
872 case "assets": 877 case "assets":
873 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 878 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
874 879
875 Util.FireAndForget(delegate { 880 Util.FireAndForget(delegate {
876 int assetReferenceTotal = TouchAllSceneAssets(true); 881 int assetsCached = CacheScenes();
877 m_log.InfoFormat( 882 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
878 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
879 assetReferenceTotal);
880 }); 883 });
881 884
882 break; 885 break;
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..c91b25f 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,6 +35,7 @@ using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
38using OpenSim.Framework; 39using OpenSim.Framework;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.Framework.Scenes.Serialization; 41using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index acd156e..951afd7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -286,20 +286,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
288 { 288 {
289 if (!Enabled)
290 return false;
291
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp))
293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true;
296 }
297
298 return false;
299 }
300
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
302 {
303 lock (sp.AttachmentsSyncLock) 289 lock (sp.AttachmentsSyncLock)
304 { 290 {
305// m_log.DebugFormat( 291// m_log.DebugFormat(
@@ -475,11 +461,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
475 461
476 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 462 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
477 { 463 {
478 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
479 }
480
481 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
482 {
483 if (!Enabled) 464 if (!Enabled)
484 return; 465 return;
485 466
@@ -521,11 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
521 so.FromItemID = UUID.Zero; 502 so.FromItemID = UUID.Zero;
522 503
523 SceneObjectPart rootPart = so.RootPart; 504 SceneObjectPart rootPart = so.RootPart;
524 so.AbsolutePosition = absolutePos; 505 so.AbsolutePosition = sp.AbsolutePosition;
525 if (absoluteRot != Quaternion.Identity)
526 {
527 so.UpdateGroupRotationR(absoluteRot);
528 }
529 so.AttachedAvatar = UUID.Zero; 506 so.AttachedAvatar = UUID.Zero;
530 rootPart.SetParentLocalId(0); 507 rootPart.SetParentLocalId(0);
531 so.ClearPartAttachmentData(); 508 so.ClearPartAttachmentData();
@@ -639,9 +616,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
639 616
640 if (grp.HasGroupChanged) 617 if (grp.HasGroupChanged)
641 { 618 {
642 m_log.DebugFormat( 619// m_log.DebugFormat(
643 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 620// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
644 grp.UUID, grp.AttachmentPoint); 621// grp.UUID, grp.AttachmentPoint);
645 622
646 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 623 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
647 624
@@ -885,7 +862,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
885 // This will throw if the attachment fails 862 // This will throw if the attachment fails
886 try 863 try
887 { 864 {
888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); 865 AttachObject(sp, objatt, attachmentPt, false, false, false);
889 } 866 }
890 catch (Exception e) 867 catch (Exception e)
891 { 868 {
@@ -956,9 +933,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
956 933
957 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 934 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
958 item = m_scene.InventoryService.GetItem(item); 935 item = m_scene.InventoryService.GetItem(item);
959 if (item == null)
960 return;
961
962 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 936 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
963 if (changed && m_scene.AvatarFactory != null) 937 if (changed && m_scene.AvatarFactory != null)
964 { 938 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 4e9d3f9..d9a619d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -62,10 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
62 public class AttachmentsModuleTests : OpenSimTestCase 62 public class AttachmentsModuleTests : OpenSimTestCase
63 { 63 {
64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false); 64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
65// private OSChatMessage m_osChatMessageReceived; 65 private OSChatMessage m_osChatMessageReceived;
66
67 // Used to test whether the operations have fired the attach event. Must be reset after each test.
68 private int m_numberOfAttachEventsFired;
69 66
70 [TestFixtureSetUp] 67 [TestFixtureSetUp]
71 public void FixtureInit() 68 public void FixtureInit()
@@ -86,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
86 { 83 {
87// Console.WriteLine("Got chat [{0}]", oscm.Message); 84// Console.WriteLine("Got chat [{0}]", oscm.Message);
88 85
89// m_osChatMessageReceived = oscm; 86 m_osChatMessageReceived = oscm;
90 m_chatEvent.Set(); 87 m_chatEvent.Set();
91 } 88 }
92 89
@@ -102,8 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
102 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); 99 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
103 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); 100 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
104 101
105 scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++;
106
107 return scene; 102 return scene;
108 } 103 }
109 104
@@ -186,8 +181,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
186 TestHelpers.InMethod(); 181 TestHelpers.InMethod();
187// TestHelpers.EnableLogging(); 182// TestHelpers.EnableLogging();
188 183
189 m_numberOfAttachEventsFired = 0;
190
191 Scene scene = CreateTestScene(); 184 Scene scene = CreateTestScene();
192 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 185 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
193 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 186 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -196,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
196 189
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 191
199 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
201 193
202 // Check status on scene presence 194 // Check status on scene presence
@@ -224,8 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
224 216
225 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 217 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
226 218
227 // Check events 219// TestHelpers.DisableLogging();
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
229 } 220 }
230 221
231 /// <summary> 222 /// <summary>
@@ -237,8 +228,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
237 TestHelpers.InMethod(); 228 TestHelpers.InMethod();
238// TestHelpers.EnableLogging(); 229// TestHelpers.EnableLogging();
239 230
240 m_numberOfAttachEventsFired = 0;
241
242 Scene scene = CreateTestScene(); 231 Scene scene = CreateTestScene();
243 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 232 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
244 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 233 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -258,9 +247,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
258 247
259 Assert.That(sp.HasAttachments(), Is.False); 248 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
261
262 // Check events
263 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
264 } 250 }
265 251
266 [Test] 252 [Test]
@@ -275,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
275 261
276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 262 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
277 263
278 m_numberOfAttachEventsFired = 0;
279 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 264 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
280 sp, attItem.ID, (uint)AttachmentPoint.Chest); 265 sp, attItem.ID, (uint)AttachmentPoint.Chest);
281 266
@@ -295,9 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 280 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
296 281
297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 282 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
298
299 // Check events
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
301 } 283 }
302 284
303 /// <summary> 285 /// <summary>
@@ -356,8 +338,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
356 ISceneEntity so 338 ISceneEntity so
357 = scene.AttachmentsModule.RezSingleAttachmentFromInventory( 339 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
358 sp, attItem.ID, (uint)AttachmentPoint.Chest); 340 sp, attItem.ID, (uint)AttachmentPoint.Chest);
359
360 m_numberOfAttachEventsFired = 0;
361 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); 341 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
362 342
363 // Check scene presence status 343 // Check scene presence status
@@ -373,9 +353,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
373 353
374 // Check object in scene 354 // Check object in scene
375 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 355 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
376
377 // Check events
378 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
379 } 356 }
380 357
381 [Test] 358 [Test]
@@ -392,8 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
392 SceneObjectGroup so 369 SceneObjectGroup so
393 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( 370 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
394 sp, attItem.ID, (uint)AttachmentPoint.Chest); 371 sp, attItem.ID, (uint)AttachmentPoint.Chest);
395
396 m_numberOfAttachEventsFired = 0;
397 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); 372 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
398 373
399 // Check status on scene presence 374 // Check status on scene presence
@@ -405,9 +380,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
405 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 380 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
406 381
407 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 382 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
408
409 // Check events
410 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
411 } 383 }
412 384
413 /// <summary> 385 /// <summary>
@@ -489,14 +461,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
489 461
490 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
491 463
492 m_numberOfAttachEventsFired = 0; 464 scene.IncomingCloseAgent(presence.UUID);
493 scene.IncomingCloseAgent(presence.UUID, false);
494 465
495 // Check that we can't retrieve this attachment from the scene. 466 // Check that we can't retrieve this attachment from the scene.
496 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
497
498 // Check events
499 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
500 } 468 }
501 469
502 [Test] 470 [Test]
@@ -512,8 +480,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
512 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 480 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
513 acd.Appearance = new AvatarAppearance(); 481 acd.Appearance = new AvatarAppearance();
514 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 482 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
515
516 m_numberOfAttachEventsFired = 0;
517 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 483 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
518 484
519 Assert.That(presence.HasAttachments(), Is.True); 485 Assert.That(presence.HasAttachments(), Is.True);
@@ -536,9 +502,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
536 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 502 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
537 503
538 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
539
540 // Check events. We expect OnAttach to fire on login.
541 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
542 } 505 }
543 506
544 [Test] 507 [Test]
@@ -559,14 +522,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
559 522
560 Vector3 newPosition = new Vector3(1, 2, 4); 523 Vector3 newPosition = new Vector3(1, 2, 4);
561 524
562 m_numberOfAttachEventsFired = 0;
563 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); 525 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
564 526
565 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); 527 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
566 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); 528 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
567
568 // Check events
569 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
570 } 529 }
571 530
572 [Test] 531 [Test]
@@ -615,7 +574,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
615 Vector3 teleportPosition = new Vector3(10, 11, 12); 574 Vector3 teleportPosition = new Vector3(10, 11, 12);
616 Vector3 teleportLookAt = new Vector3(20, 21, 22); 575 Vector3 teleportLookAt = new Vector3(20, 21, 22);
617 576
618 m_numberOfAttachEventsFired = 0;
619 sceneA.RequestTeleportLocation( 577 sceneA.RequestTeleportLocation(
620 beforeTeleportSp.ControllingClient, 578 beforeTeleportSp.ControllingClient,
621 sceneB.RegionInfo.RegionHandle, 579 sceneB.RegionInfo.RegionHandle,
@@ -658,9 +616,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
658 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); 616 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
659 617
660 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); 618 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
661
662 // Check events
663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
664 } 619 }
620
621 // I'm commenting this test because scene setup NEEDS InventoryService to
622 // be non-null
623 //[Test]
624// public void T032_CrossAttachments()
625// {
626// TestHelpers.InMethod();
627//
628// ScenePresence presence = scene.GetScenePresence(agent1);
629// ScenePresence presence2 = scene2.GetScenePresence(agent1);
630// presence2.AddAttachment(sog1);
631// presence2.AddAttachment(sog2);
632//
633// ISharedRegionModule serialiser = new SerialiserModule();
634// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser);
635// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser);
636//
637// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross");
638//
639// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful");
640// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted");
641// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects");
642// }
665 } 643 }
666} 644}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index e3bf997..4cb4370 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -533,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
533 // Ignore ruth's assets 533 // Ignore ruth's assets
534 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 534 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
535 continue; 535 continue;
536
537 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 536 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
538 baseItem = invService.GetItem(baseItem); 537 baseItem = invService.GetItem(baseItem);
539 538
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 4407e40..dbbb0ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -197,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
197 string fromName = c.From; 197 string fromName = c.From;
198 string fromNamePrefix = ""; 198 string fromNamePrefix = "";
199 UUID fromID = UUID.Zero; 199 UUID fromID = UUID.Zero;
200 UUID ownerID = UUID.Zero;
201 string message = c.Message; 200 string message = c.Message;
202 IScene scene = c.Scene; 201 IScene scene = c.Scene;
203 UUID destination = c.Destination; 202 UUID destination = c.Destination;
@@ -225,16 +224,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
225 fromNamePrefix = m_adminPrefix; 224 fromNamePrefix = m_adminPrefix;
226 } 225 }
227 destination = UUID.Zero; // Avatars cant "SayTo" 226 destination = UUID.Zero; // Avatars cant "SayTo"
228 ownerID = c.Sender.AgentId;
229
230 break; 227 break;
231 228
232 case ChatSourceType.Object: 229 case ChatSourceType.Object:
233 fromID = c.SenderUUID; 230 fromID = c.SenderUUID;
234 231
235 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
236 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
237
238 break; 232 break;
239 } 233 }
240 234
@@ -268,16 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // objects on a parcel with access restrictions 262 // objects on a parcel with access restrictions
269 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) 263 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
270 { 264 {
271 if (destination != UUID.Zero) 265 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType))
272 { 266 receiverIDs.Add(presence.UUID);
273 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
274 receiverIDs.Add(presence.UUID);
275 }
276 else
277 {
278 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
279 receiverIDs.Add(presence.UUID);
280 }
281 } 267 }
282 } 268 }
283 } 269 }
@@ -338,7 +324,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
338 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 324 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
339 return; 325 return;
340 326
341 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, 327 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
342 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 328 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
343 receiverIDs.Add(client.AgentId); 329 receiverIDs.Add(client.AgentId);
344 } 330 }
@@ -355,20 +341,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
355 /// <param name="fromPos"></param> 341 /// <param name="fromPos"></param>
356 /// <param name="regionPos">/param> 342 /// <param name="regionPos">/param>
357 /// <param name="fromAgentID"></param> 343 /// <param name="fromAgentID"></param>
358 /// <param name='ownerID'>
359 /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID.
360 /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762
361 /// </param>
362 /// <param name="fromName"></param> 344 /// <param name="fromName"></param>
363 /// <param name="type"></param> 345 /// <param name="type"></param>
364 /// <param name="message"></param> 346 /// <param name="message"></param>
365 /// <param name="src"></param> 347 /// <param name="src"></param>
366 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 348 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
367 /// precondition</returns> 349 /// precondition</returns>
368 protected virtual bool TrySendChatMessage( 350 protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
369 ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 351 UUID fromAgentID, string fromName, ChatTypeEnum type,
370 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 352 string message, ChatSourceType src)
371 string message, ChatSourceType src, bool ignoreDistance)
372 { 353 {
373 // don't send chat to child agents 354 // don't send chat to child agents
374 if (presence.IsChildAgent) return false; 355 if (presence.IsChildAgent) return false;
@@ -388,9 +369,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
388 } 369 }
389 370
390 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 371 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
391 presence.ControllingClient.SendChatMessage( 372 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName,
392 message, (byte) type, fromPos, fromName, 373 fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully);
393 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
394 374
395 return true; 375 return true;
396 } 376 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index 5ec0ea9..d942e87 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
141 client.FirstName+" "+client.LastName, 141 client.FirstName+" "+client.LastName,
142 destID, (byte)211, false, 142 destID, (byte)211, false,
143 String.Empty, 143 String.Empty,
144 transactionID, false, new Vector3(), new byte[0], true), 144 transactionID, false, new Vector3(), new byte[0]),
145 delegate(bool success) {} ); 145 delegate(bool success) {} );
146 } 146 }
147 } 147 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index f1903c3..24ec435 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -28,7 +28,6 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
32using System.Reflection; 31using System.Reflection;
33using System.Threading; 32using System.Threading;
34using log4net; 33using log4net;
@@ -483,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
483 Util.FireAndForget( 482 Util.FireAndForget(
484 delegate 483 delegate
485 { 484 {
486// m_log.DebugFormat( 485 m_log.DebugFormat(
487// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
488// friendList.Count, agentID, online); 487 friendList.Count, agentID, online);
489 488
490 // Notify about this user status 489 // Notify about this user status
491 StatusNotify(friendList, agentID, online); 490 StatusNotify(friendList, agentID, online);
@@ -496,36 +495,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
496 495
497 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 496 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
498 { 497 {
499 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); 498 foreach (FriendInfo friend in friendList)
500 List<string> remoteFriendStringIds = new List<string>();
501 foreach (string friendStringId in friendStringIds)
502 { 499 {
503 UUID friendUuid; 500 UUID friendID;
504 if (UUID.TryParse(friendStringId, out friendUuid)) 501 if (UUID.TryParse(friend.Friend, out friendID))
505 { 502 {
506 if (LocalStatusNotification(userID, friendUuid, online)) 503 // Try local
504 if (LocalStatusNotification(userID, friendID, online))
507 continue; 505 continue;
508 506
509 remoteFriendStringIds.Add(friendStringId); 507 // The friend is not here [as root]. Let's forward.
508 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
509 if (friendSessions != null && friendSessions.Length > 0)
510 {
511 PresenceInfo friendSession = null;
512 foreach (PresenceInfo pinfo in friendSessions)
513 {
514 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
515 {
516 friendSession = pinfo;
517 break;
518 }
519 }
520
521 if (friendSession != null)
522 {
523 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
524 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
525 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
526 }
527 }
528
529 // Friend is not online. Ignore.
510 } 530 }
511 else 531 else
512 { 532 {
513 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); 533 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
514 }
515 }
516
517 // We do this regrouping so that we can efficiently send a single request rather than one for each
518 // friend in what may be a very large friends list.
519 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
520
521 foreach (PresenceInfo friendSession in friendSessions)
522 {
523 // let's guard against sessions-gone-bad
524 if (friendSession.RegionID != UUID.Zero)
525 {
526 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
527 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
528 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
529 } 534 }
530 } 535 }
531 } 536 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 82816d9..716cc69 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
206 transferModule.SendInstantMessage(new GridInstantMessage( 206 transferModule.SendInstantMessage(new GridInstantMessage(
207 m_scene, godID, "God", agentID, (byte)250, false, 207 m_scene, godID, "God", agentID, (byte)250, false,
208 Utils.BytesToString(reason), UUID.Zero, true, 208 Utils.BytesToString(reason), UUID.Zero, true,
209 new Vector3(), new byte[] {(byte)kickflags}, true), 209 new Vector3(), new byte[] {(byte)kickflags}),
210 delegate(bool success) {} ); 210 delegate(bool success) {} );
211 } 211 }
212 return; 212 return;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index d0e88f6..6587ead 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
166 166
167 if (options.ContainsKey("verbose")) 167 if (options.ContainsKey("verbose"))
168 m_log.InfoFormat( 168 m_log.InfoFormat(
169 "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); 170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID);
171 171
172 string filename = path + CreateArchiveItemName(inventoryItem); 172 string filename = path + CreateArchiveItemName(inventoryItem);
@@ -337,14 +337,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
337 { 337 {
338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); 338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count);
339 339
340 AssetsRequest ar 340 new AssetsRequest(
341 = new AssetsRequest( 341 new AssetsArchiver(m_archiveWriter),
342 new AssetsArchiver(m_archiveWriter), 342 m_assetUuids, m_scene.AssetService,
343 m_assetUuids, m_scene.AssetService, 343 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
344 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 344 options, ReceivedAllAssets).Execute();
345 options, ReceivedAllAssets);
346
347 Util.FireAndForget(o => ar.Execute());
348 } 345 }
349 else 346 else
350 { 347 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 765b960..7d1fe68 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -35,7 +35,6 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Console;
39using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
@@ -210,9 +209,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
210 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
211 Dictionary<string, object> options) 210 Dictionary<string, object> options)
212 { 211 {
213// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
214// return false;
215
216 if (m_scenes.Count > 0) 212 if (m_scenes.Count > 0)
217 { 213 {
218 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 00727a4..1056865 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -82,25 +82,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
82 82
83 protected string m_item1Name = "Ray Gun Item"; 83 protected string m_item1Name = "Ray Gun Item";
84 protected string m_coaItemName = "Coalesced Item"; 84 protected string m_coaItemName = "Coalesced Item";
85 85
86 [TestFixtureSetUp]
87 public void FixtureSetup()
88 {
89 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
90 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
91
92 ConstructDefaultIarBytesForTestLoad();
93 }
94
95 [TestFixtureTearDown]
96 public void TearDown()
97 {
98 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
99 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
100 // tests really shouldn't).
101 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
102 }
103
104 [SetUp] 86 [SetUp]
105 public override void SetUp() 87 public override void SetUp()
106 { 88 {
@@ -108,6 +90,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
108 m_iarStream = new MemoryStream(m_iarStreamBytes); 90 m_iarStream = new MemoryStream(m_iarStreamBytes);
109 } 91 }
110 92
93 [TestFixtureSetUp]
94 public void FixtureSetup()
95 {
96 ConstructDefaultIarBytesForTestLoad();
97 }
98
111 protected void ConstructDefaultIarBytesForTestLoad() 99 protected void ConstructDefaultIarBytesForTestLoad()
112 { 100 {
113// log4net.Config.XmlConfigurator.Configure(); 101// log4net.Config.XmlConfigurator.Configure();
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 06f6e49..b112b6d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class InventoryArchiverTests : InventoryArchiveTestCase 51 public class InventoryArchiverTests : InventoryArchiveTestCase
52 { 52 {
53 protected TestScene m_scene; 53 protected TestScene m_scene;
54 protected InventoryArchiverModule m_archiverModule; 54 protected InventoryArchiverModule m_archiverModule;
55 55
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
69 public void TestLoadCoalesecedItem() 69 public void TestLoadCoalesecedItem()
70 { 70 {
71 TestHelpers.InMethod(); 71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging(); 72// log4net.Config.XmlConfigurator.Configure();
73 73
74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); 74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); 75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
351 } 351 }
352 352
353// /// <summary> 353 /// <summary>
354// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 354 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
355// /// an account exists with the same name as the creator, though not the same id. 355 /// an account exists with the same name as the creator, though not the same id.
356// /// </summary> 356 /// </summary>
357// [Test] 357 [Test]
358// public void TestLoadIarV0_1SameNameCreator() 358 public void TestLoadIarV0_1SameNameCreator()
359// { 359 {
360// TestHelpers.InMethod(); 360 TestHelpers.InMethod();
361// TestHelpers.EnableLogging(); 361// log4net.Config.XmlConfigurator.Configure();
362// 362
363// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 363 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
364// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 364 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
365// 365
366// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 366 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
367// InventoryItemBase foundItem1 367 InventoryItemBase foundItem1
368// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 368 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
369// 369
370// Assert.That( 370 Assert.That(
371// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 371 foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
372// "Loaded item non-uuid creator doesn't match original"); 372 "Loaded item non-uuid creator doesn't match original");
373// Assert.That( 373 Assert.That(
374// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 374 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
375// "Loaded item uuid creator doesn't match original"); 375 "Loaded item uuid creator doesn't match original");
376// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 376 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
377// "Loaded item owner doesn't match inventory reciever"); 377 "Loaded item owner doesn't match inventory reciever");
378// 378
379// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 379 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
380// string xmlData = Utils.BytesToString(asset1.Data); 380 string xmlData = Utils.BytesToString(asset1.Data);
381// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 381 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
382// 382
383// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 383 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
384// } 384 }
385 385
386 /// <summary> 386 /// <summary>
387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index e26beec..8176989 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces;
38 38
39namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer 39namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
40{ 40{
41 public class InventoryTransferModule : ISharedRegionModule 41 public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule
42 { 42 {
43 private static readonly ILog m_log 43 private static readonly ILog m_log
44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 /// <summary> 46 /// <summary>
47 private List<Scene> m_Scenelist = new List<Scene>(); 47 private List<Scene> m_Scenelist = new List<Scene>();
48// private Dictionary<UUID, Scene> m_AgentRegions = 48 private Dictionary<UUID, Scene> m_AgentRegions =
49// new Dictionary<UUID, Scene>(); 49 new Dictionary<UUID, Scene>();
50 50
51 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule = null;
52 private bool m_Enabled = true; 52 private bool m_Enabled = true;
@@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
76 76
77 m_Scenelist.Add(scene); 77 m_Scenelist.Add(scene);
78 78
79// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
80 80
81 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
82// scene.EventManager.OnClientClosed += ClientLoggedOut; 82 scene.EventManager.OnClientClosed += ClientLoggedOut;
83 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 83 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
84// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; 84 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
85 } 85 }
86 86
87 public void RegionLoaded(Scene scene) 87 public void RegionLoaded(Scene scene)
@@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 96
97 m_Scenelist.Clear(); 97 m_Scenelist.Clear();
98 scene.EventManager.OnNewClient -= OnNewClient; 98 scene.EventManager.OnNewClient -= OnNewClient;
99// scene.EventManager.OnClientClosed -= ClientLoggedOut; 99 scene.EventManager.OnClientClosed -= ClientLoggedOut;
100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
101// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 101 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
102 } 102 }
103 } 103 }
104 } 104 }
@@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
106 public void RemoveRegion(Scene scene) 106 public void RemoveRegion(Scene scene)
107 { 107 {
108 scene.EventManager.OnNewClient -= OnNewClient; 108 scene.EventManager.OnNewClient -= OnNewClient;
109// scene.EventManager.OnClientClosed -= ClientLoggedOut; 109 scene.EventManager.OnClientClosed -= ClientLoggedOut;
110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
111// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 111 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
112 m_Scenelist.Remove(scene); 112 m_Scenelist.Remove(scene);
113 } 113 }
114 114
@@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
138 client.OnInstantMessage += OnInstantMessage; 138 client.OnInstantMessage += OnInstantMessage;
139 } 139 }
140 140
141// protected void OnSetRootAgentScene(UUID id, Scene scene) 141 protected void OnSetRootAgentScene(UUID id, Scene scene)
142// { 142 {
143// m_AgentRegions[id] = scene; 143 m_AgentRegions[id] = scene;
144// } 144 }
145 145
146 private Scene FindClientScene(UUID agentId) 146 private Scene FindClientScene(UUID agentId)
147 { 147 {
@@ -313,11 +313,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); 313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
314 } 314 }
315 } 315 }
316
317 // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name>
318 // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis
319 // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously
320 // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here.
321 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 316 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
322 { 317 {
323 UUID destinationFolderID = UUID.Zero; 318 UUID destinationFolderID = UUID.Zero;
@@ -329,16 +324,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
329 324
330 if (destinationFolderID != UUID.Zero) 325 if (destinationFolderID != UUID.Zero)
331 { 326 {
332 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
333 if (destinationFolder == null)
334 {
335 m_log.WarnFormat(
336 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
337 client.Name, scene.Name, destinationFolderID);
338
339 return;
340 }
341
342 IInventoryService invService = scene.InventoryService; 327 IInventoryService invService = scene.InventoryService;
343 328
344 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
@@ -346,11 +331,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
346 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 331 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
347 item = invService.GetItem(item); 332 item = invService.GetItem(item);
348 InventoryFolderBase folder = null; 333 InventoryFolderBase folder = null;
349 UUID? previousParentFolderID = null;
350 334
351 if (item != null) // It's an item 335 if (item != null) // It's an item
352 { 336 {
353 previousParentFolderID = item.Folder;
354 item.Folder = destinationFolderID; 337 item.Folder = destinationFolderID;
355 338
356 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 339 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
@@ -363,22 +346,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
363 346
364 if (folder != null) // It's a folder 347 if (folder != null) // It's a folder
365 { 348 {
366 previousParentFolderID = folder.ParentID;
367 folder.ParentID = destinationFolderID; 349 folder.ParentID = destinationFolderID;
368 invService.MoveFolder(folder); 350 invService.MoveFolder(folder);
369 } 351 }
370 } 352 }
371
372 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
373 if (previousParentFolderID != null)
374 {
375 InventoryFolderBase previousParentFolder
376 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
377 previousParentFolder = invService.GetFolder(previousParentFolder);
378 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
379
380 scene.SendInventoryUpdate(client, destinationFolder, true, true);
381 }
382 } 353 }
383 } 354 }
384 else if ( 355 else if (
@@ -399,11 +370,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
399 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 370 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
400 item = invService.GetItem(item); 371 item = invService.GetItem(item);
401 InventoryFolderBase folder = null; 372 InventoryFolderBase folder = null;
402 UUID? previousParentFolderID = null;
403 373
404 if (item != null && trashFolder != null) 374 if (item != null && trashFolder != null)
405 { 375 {
406 previousParentFolderID = item.Folder;
407 item.Folder = trashFolder.ID; 376 item.Folder = trashFolder.ID;
408 377
409 // Diva comment: can't we just update this item??? 378 // Diva comment: can't we just update this item???
@@ -419,7 +388,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
419 388
420 if (folder != null & trashFolder != null) 389 if (folder != null & trashFolder != null)
421 { 390 {
422 previousParentFolderID = folder.ParentID;
423 folder.ParentID = trashFolder.ID; 391 folder.ParentID = trashFolder.ID;
424 invService.MoveFolder(folder); 392 invService.MoveFolder(folder);
425 client.SendBulkUpdateInventory(folder); 393 client.SendBulkUpdateInventory(folder);
@@ -440,16 +408,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
440 client.SendAgentAlertMessage("Unable to delete "+ 408 client.SendAgentAlertMessage("Unable to delete "+
441 "received inventory" + reason, false); 409 "received inventory" + reason, false);
442 } 410 }
443 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
444 else if (previousParentFolderID != null)
445 {
446 InventoryFolderBase previousParentFolder
447 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
448 previousParentFolder = invService.GetFolder(previousParentFolder);
449 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
450
451 scene.SendInventoryUpdate(client, trashFolder, true, true);
452 }
453 411
454 if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) 412 if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined)
455 { 413 {
@@ -468,69 +426,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
468 } 426 }
469 } 427 }
470 428
471// public bool NeedSceneCacheClear(UUID agentID, Scene scene) 429 public bool NeedSceneCacheClear(UUID agentID, Scene scene)
472// { 430 {
473// if (!m_AgentRegions.ContainsKey(agentID)) 431 if (!m_AgentRegions.ContainsKey(agentID))
474// { 432 {
475// // Since we can get here two ways, we need to scan 433 // Since we can get here two ways, we need to scan
476// // the scenes here. This is somewhat more expensive 434 // the scenes here. This is somewhat more expensive
477// // but helps avoid a nasty bug 435 // but helps avoid a nasty bug
478// // 436 //
479// 437
480// foreach (Scene s in m_Scenelist) 438 foreach (Scene s in m_Scenelist)
481// { 439 {
482// ScenePresence presence; 440 ScenePresence presence;
483// 441
484// if (s.TryGetScenePresence(agentID, out presence)) 442 if (s.TryGetScenePresence(agentID, out presence))
485// { 443 {
486// // If the agent is in this scene, then we 444 // If the agent is in this scene, then we
487// // are being called twice in a single 445 // are being called twice in a single
488// // teleport. This is wasteful of cycles 446 // teleport. This is wasteful of cycles
489// // but harmless due to this 2nd level check 447 // but harmless due to this 2nd level check
490// // 448 //
491// // If the agent is found in another scene 449 // If the agent is found in another scene
492// // then the list wasn't current 450 // then the list wasn't current
493// // 451 //
494// // If the agent is totally unknown, then what 452 // If the agent is totally unknown, then what
495// // are we even doing here?? 453 // are we even doing here??
496// // 454 //
497// if (s == scene) 455 if (s == scene)
498// { 456 {
499// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); 457 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
500// return true; 458 return true;
501// } 459 }
502// else 460 else
503// { 461 {
504// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); 462 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
505// return false; 463 return false;
506// } 464 }
507// } 465 }
508// } 466 }
509// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); 467 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
510// return true; 468 return true;
511// } 469 }
512// 470
513// // The agent is left in current Scene, so we must be 471 // The agent is left in current Scene, so we must be
514// // going to another instance 472 // going to another instance
515// // 473 //
516// if (m_AgentRegions[agentID] == scene) 474 if (m_AgentRegions[agentID] == scene)
517// { 475 {
518// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); 476 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
519// m_AgentRegions.Remove(agentID); 477 m_AgentRegions.Remove(agentID);
520// return true; 478 return true;
521// } 479 }
522// 480
523// // Another region has claimed the agent 481 // Another region has claimed the agent
524// // 482 //
525// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); 483 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
526// return false; 484 return false;
527// } 485 }
528// 486
529// public void ClientLoggedOut(UUID agentID, Scene scene) 487 public void ClientLoggedOut(UUID agentID, Scene scene)
530// { 488 {
531// if (m_AgentRegions.ContainsKey(agentID)) 489 if (m_AgentRegions.ContainsKey(agentID))
532// m_AgentRegions.Remove(agentID); 490 m_AgentRegions.Remove(agentID);
533// } 491 }
534 492
535 /// <summary> 493 /// <summary>
536 /// 494 ///
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 9c369f6..92cf9d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
186 client.FirstName+" "+client.LastName, targetid, 186 client.FirstName+" "+client.LastName, targetid,
187 (byte)InstantMessageDialog.RequestTeleport, false, 187 (byte)InstantMessageDialog.RequestTeleport, false,
188 message, sessionID, false, presence.AbsolutePosition, 188 message, sessionID, false, presence.AbsolutePosition,
189 new Byte[0], true); 189 new Byte[0]);
190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid; 190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
191 191
192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); 192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 1949459..a889984 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
173 client.FirstName+" "+client.LastName, targetid, 173 client.FirstName+" "+client.LastName, targetid,
174 (byte)InstantMessageDialog.GodLikeRequestTeleport, false, 174 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
175 message, dest, false, presence.AbsolutePosition, 175 message, dest, false, presence.AbsolutePosition,
176 new Byte[0], true); 176 new Byte[0]);
177 } 177 }
178 else 178 else
179 { 179 {
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
181 client.FirstName+" "+client.LastName, targetid, 181 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false, 182 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, dest, false, presence.AbsolutePosition, 183 message, dest, false, presence.AbsolutePosition,
184 new Byte[0], true); 184 new Byte[0]);
185 } 185 }
186 186
187 if (m_TransferModule != null) 187 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 31e6ce9..880b2cc 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -327,14 +327,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
327 return; 327 return;
328 } 328 }
329 329
330 // Validate assorted conditions
331 string reason = string.Empty;
332 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
333 {
334 sp.ControllingClient.SendTeleportFailed(reason);
335 return;
336 }
337
338 // 330 //
339 // This is it 331 // This is it
340 // 332 //
@@ -366,13 +358,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
366 } 358 }
367 } 359 }
368 360
369 // Nothing to validate here
370 protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
371 {
372 reason = String.Empty;
373 return true;
374 }
375
376 /// <summary> 361 /// <summary>
377 /// Determines whether this instance is within the max transfer distance. 362 /// Determines whether this instance is within the max transfer distance.
378 /// </summary> 363 /// </summary>
@@ -488,11 +473,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
488 // both regions 473 // both regions
489 if (sp.ParentID != (uint)0) 474 if (sp.ParentID != (uint)0)
490 sp.StandUp(); 475 sp.StandUp();
476
491 else if (sp.Flying) 477 else if (sp.Flying)
492 teleportFlags |= (uint)TeleportFlags.IsFlying; 478 teleportFlags |= (uint)TeleportFlags.IsFlying;
493 479
494 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
495 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
496 sp.ControllingClient.SendTeleportStart(teleportFlags); 480 sp.ControllingClient.SendTeleportStart(teleportFlags);
497 481
498 // the avatar.Close below will clear the child region list. We need this below for (possibly) 482 // the avatar.Close below will clear the child region list. We need this below for (possibly)
@@ -568,11 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
568 // So let's wait 552 // So let's wait
569 Thread.Sleep(200); 553 Thread.Sleep(200);
570 554
571 // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
572 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
573 // only on TeleportFinish). This is untested for region teleport between different simulators
574 // though this probably also works.
575 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 555 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
556
576 } 557 }
577 else 558 else
578 { 559 {
@@ -593,7 +574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
593 574
594 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 575 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
595 576
596 if (!UpdateAgent(reg, finalDestination, agent, sp)) 577 if (!UpdateAgent(reg, finalDestination, agent))
597 { 578 {
598 // Region doesn't take it 579 // Region doesn't take it
599 m_log.WarnFormat( 580 m_log.WarnFormat(
@@ -669,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
669 // an agent cannot teleport back to this region if it has teleported away. 650 // an agent cannot teleport back to this region if it has teleported away.
670 Thread.Sleep(3000); 651 Thread.Sleep(3000);
671 652
672 sp.Scene.IncomingCloseAgent(sp.UUID, false); 653 sp.Scene.IncomingCloseAgent(sp.UUID);
673 } 654 }
674 else 655 else
675 { 656 {
@@ -677,14 +658,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
677 sp.Reset(); 658 sp.Reset();
678 } 659 }
679 660
680 // Commented pending deletion since this method no longer appears to do anything at all 661 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
681// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 662 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
682// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) 663 {
683// { 664 m_log.DebugFormat(
684// m_log.DebugFormat( 665 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
685// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", 666 sp.UUID);
686// sp.UUID); 667 }
687// }
688 668
689 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 669 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
690 } 670 }
@@ -721,7 +701,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
721 return success; 701 return success;
722 } 702 }
723 703
724 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 704 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
725 { 705 {
726 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 706 return Scene.SimulationService.UpdateAgent(finalDestination, agent);
727 } 707 }
@@ -1033,7 +1013,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1033 Scene initiatingScene) 1013 Scene initiatingScene)
1034 { 1014 {
1035 Thread.Sleep(10000); 1015 Thread.Sleep(10000);
1036
1037 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1016 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1038 if (im != null) 1017 if (im != null)
1039 { 1018 {
@@ -1046,22 +1025,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1046 (uint)(int)position.X, 1025 (uint)(int)position.X,
1047 (uint)(int)position.Y, 1026 (uint)(int)position.Y,
1048 (uint)(int)position.Z); 1027 (uint)(int)position.Z);
1049 1028 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero,
1050 GridInstantMessage m 1029 "Region", agent.UUID,
1051 = new GridInstantMessage( 1030 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
1052 initiatingScene, 1031 "", gotoLocation, false, new Vector3(127, 0, 0),
1053 UUID.Zero, 1032 new Byte[0]);
1054 "Region",
1055 agent.UUID,
1056 (byte)InstantMessageDialog.GodLikeRequestTeleport,
1057 false,
1058 "",
1059 gotoLocation,
1060 false,
1061 new Vector3(127, 0, 0),
1062 new Byte[0],
1063 false);
1064
1065 im.SendInstantMessage(m, delegate(bool success) 1033 im.SendInstantMessage(m, delegate(bool success)
1066 { 1034 {
1067 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); 1035 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
@@ -1223,11 +1191,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1223 // the user may change their profile information in other region, 1191 // the user may change their profile information in other region,
1224 // so the userinfo in UserProfileCache is not reliable any more, delete it 1192 // so the userinfo in UserProfileCache is not reliable any more, delete it
1225 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1193 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1226// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) 1194 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1227// { 1195 {
1228// m_log.DebugFormat( 1196 m_log.DebugFormat(
1229// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); 1197 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1230// } 1198 }
1231 1199
1232 //m_log.Debug("AFTER CROSS"); 1200 //m_log.Debug("AFTER CROSS");
1233 //Scene.DumpChildrenSeeds(UUID); 1201 //Scene.DumpChildrenSeeds(UUID);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index b16c37a..3010b59 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -54,59 +54,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
54 54
55 private GatekeeperServiceConnector m_GatekeeperConnector; 55 private GatekeeperServiceConnector m_GatekeeperConnector;
56 56
57 protected bool m_RestrictAppearanceAbroad;
58 protected string m_AccountName;
59 protected List<AvatarAppearance> m_ExportedAppearances;
60 protected List<AvatarAttachment> m_Attachs;
61
62 protected List<AvatarAppearance> ExportedAppearance
63 {
64 get
65 {
66 if (m_ExportedAppearances != null)
67 return m_ExportedAppearances;
68
69 m_ExportedAppearances = new List<AvatarAppearance>();
70 m_Attachs = new List<AvatarAttachment>();
71
72 string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
73
74 foreach (string name in names)
75 {
76 string[] parts = name.Trim().Split();
77 if (parts.Length != 2)
78 {
79 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name);
80 return null;
81 }
82 UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]);
83 if (account == null)
84 {
85 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName);
86 return null;
87 }
88 AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID);
89 if (a != null)
90 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name);
91
92 foreach (AvatarAttachment att in a.GetAttachments())
93 {
94 InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID);
95 item = Scene.InventoryService.GetItem(item);
96 if (item != null)
97 a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID);
98 else
99 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name);
100 }
101
102 m_ExportedAppearances.Add(a);
103 m_Attachs.AddRange(a.GetAttachments());
104 }
105
106 return m_ExportedAppearances;
107 }
108 }
109
110 #region ISharedRegionModule 57 #region ISharedRegionModule
111 58
112 public override string Name 59 public override string Name
@@ -125,18 +72,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
125 { 72 {
126 IConfig transferConfig = source.Configs["EntityTransfer"]; 73 IConfig transferConfig = source.Configs["EntityTransfer"];
127 if (transferConfig != null) 74 if (transferConfig != null)
128 {
129 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); 75 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
130 76
131 m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false);
132 if (m_RestrictAppearanceAbroad)
133 {
134 m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty);
135 if (m_AccountName == string.Empty)
136 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!");
137 }
138 }
139
140 InitialiseCommon(source); 77 InitialiseCommon(source);
141 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 78 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
142 } 79 }
@@ -148,36 +85,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
148 base.AddRegion(scene); 85 base.AddRegion(scene);
149 86
150 if (m_Enabled) 87 if (m_Enabled)
151 {
152 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 88 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
153 scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject;
154 }
155 }
156
157 void OnIncomingSceneObject(SceneObjectGroup so)
158 {
159 if (!so.IsAttachment)
160 return;
161
162 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
163 return;
164
165 // foreign user
166 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
167 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
168 {
169 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
170 {
171 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
172 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
173 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
174 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url);
175 uuidGatherer.GatherAssetUuids(so, ids);
176
177 foreach (KeyValuePair<UUID, AssetType> kvp in ids)
178 uuidGatherer.FetchAsset(kvp.Key);
179 }
180 }
181 } 89 }
182 90
183 protected override void OnNewClient(IClientAPI client) 91 protected override void OnNewClient(IClientAPI client)
@@ -212,7 +120,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
212 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); 120 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
213 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 121 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
214 122
215 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
216 { 124 {
217 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
218 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); 126 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
@@ -232,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
232 return true; 140 return true;
233 141
234 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 142 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
235 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 143 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
236 return true; 144 return true;
237 145
238 return false; 146 return false;
@@ -245,8 +153,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
245 { 153 {
246 // Log them out of this grid 154 // Log them out of this grid
247 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 155 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
248 string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID);
249 Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
250 } 156 }
251 } 157 }
252 158
@@ -256,11 +162,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
256 reason = string.Empty; 162 reason = string.Empty;
257 logout = false; 163 logout = false;
258 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 164 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
259 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 165 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
260 { 166 {
261 // this user is going to another grid 167 // this user is going to another grid
262 // for local users, check if HyperGrid teleport is allowed, based on user level 168 // check if HyperGrid teleport is allowed, based on user level
263 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) 169 if (sp.UserLevel < m_levelHGTeleport)
264 { 170 {
265 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); 171 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
266 reason = "Hypergrid teleport not allowed"; 172 reason = "Hypergrid teleport not allowed";
@@ -294,124 +200,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
294 TeleportHome(id, client); 200 TeleportHome(id, client);
295 } 201 }
296 202
297 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
298 {
299 reason = "Please wear your grid's allowed appearance before teleporting to another grid";
300 if (!m_RestrictAppearanceAbroad)
301 return true;
302
303 // The rest is only needed for controlling appearance
304
305 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
306 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
307 {
308 // this user is going to another grid
309 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
310 {
311 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
312
313 // Check wearables
314 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
315 {
316 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
317 {
318 if (sp.Appearance.Wearables[i] == null)
319 continue;
320
321 bool found = false;
322 foreach (AvatarAppearance a in ExportedAppearance)
323 if (a.Wearables[i] != null)
324 {
325 found = true;
326 break;
327 }
328
329 if (!found)
330 {
331 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
332 return false;
333 }
334
335 found = false;
336 foreach (AvatarAppearance a in ExportedAppearance)
337 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
338 {
339 found = true;
340 break;
341 }
342
343 if (!found)
344 {
345 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
346 return false;
347 }
348 }
349 }
350
351 // Check attachments
352 foreach (AvatarAttachment att in sp.Appearance.GetAttachments())
353 {
354 bool found = false;
355 foreach (AvatarAttachment att2 in m_Attachs)
356 {
357 if (att2.AssetID == att.AssetID)
358 {
359 found = true;
360 break;
361 }
362 }
363 if (!found)
364 {
365 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint);
366 return false;
367 }
368 }
369 }
370 }
371
372 reason = string.Empty;
373 return true;
374 }
375
376
377 //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp)
378 //{
379 // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
380 // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
381 // {
382 // // this user is going to another grid
383 // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID))
384 // {
385 // // We need to strip the agent off its appearance
386 // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance");
387
388 // // Delete existing npc attachments
389 // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
390
391 // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments
392 // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true);
393 // sp.Appearance = newAppearance;
394
395 // // Rez needed npc attachments
396 // Scene.AttachmentsModule.RezAttachments(sp);
397
398
399 // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>();
400 // //module.SendAppearance(sp.UUID);
401 // module.RequestRebake(sp, false);
402
403 // Scene.AttachmentsModule.CopyAttachments(sp, agentData);
404 // agentData.Appearance = sp.Appearance;
405 // }
406 // }
407
408 // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments())
409 // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID);
410
411
412 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
413 //}
414
415 public override bool TeleportHome(UUID id, IClientAPI client) 203 public override bool TeleportHome(UUID id, IClientAPI client)
416 { 204 {
417 m_log.DebugFormat( 205 m_log.DebugFormat(
@@ -587,4 +375,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
587 return region; 375 return region;
588 } 376 }
589 } 377 }
590} 378} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index f8ec6de..eaadc1b 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
71 71
72 #region Internal functions 72 #region Internal functions
73 73
74 public AssetMetadata FetchMetadata(string url, UUID assetID) 74 public AssetBase FetchAsset(string url, UUID assetID)
75 { 75 {
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 76 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 77 url = url + "/";
78 78
79 AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); 79 AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString());
80 80
81 if (meta != null) 81 if (asset != null)
82 m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); 82 {
83 else 83 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
84 m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); 84 return asset;
85 85 }
86 return meta; 86 return null;
87 } 87 }
88 88
89 public bool PostAsset(string url, AssetBase asset) 89 public bool PostAsset(string url, AssetBase asset)
@@ -93,7 +93,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
93 if (!url.EndsWith("/") && !url.EndsWith("=")) 93 if (!url.EndsWith("/") && !url.EndsWith("="))
94 url = url + "/"; 94 url = url + "/";
95 95
96 bool success = true;
97 // See long comment in AssetCache.AddAsset 96 // See long comment in AssetCache.AddAsset
98 if (!asset.Temporary || asset.Local) 97 if (!asset.Temporary || asset.Local)
99 { 98 {
@@ -104,7 +103,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
104 // not having a global naming infrastructure 103 // not having a global naming infrastructure
105 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); 104 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
106 Copy(asset, asset1); 105 Copy(asset, asset1);
107 asset1.ID = url + asset.ID; 106 try
107 {
108 asset1.ID = url + asset.ID;
109 }
110 catch
111 {
112 m_log.Warn("[HG ASSET MAPPER]: Oops.");
113 }
108 114
109 AdjustIdentifiers(asset1.Metadata); 115 AdjustIdentifiers(asset1.Metadata);
110 if (asset1.Metadata.Type == (sbyte)AssetType.Object) 116 if (asset1.Metadata.Type == (sbyte)AssetType.Object)
@@ -112,17 +118,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
112 else 118 else
113 asset1.Data = asset.Data; 119 asset1.Data = asset.Data;
114 120
115 string id = m_scene.AssetService.Store(asset1); 121 m_scene.AssetService.Store(asset1);
116 if (id == string.Empty) 122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
117 {
118 m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID);
119 success = false;
120 }
121 else
122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
123 } 123 }
124 return success; 124 return true;
125 } 125 }
126 else 126 else
127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); 127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
128 128
@@ -222,17 +222,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
222 222
223 public void Get(UUID assetID, UUID ownerID, string userAssetURL) 223 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
224 { 224 {
225 // Get the item from the remote asset server onto the local AssetService 225 // Get the item from the remote asset server onto the local AssetCache
226 // and place an entry in m_assetMap
227
228 m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
229 AssetBase asset = FetchAsset(userAssetURL, assetID);
226 230
227 AssetMetadata meta = FetchMetadata(userAssetURL, assetID); 231 if (asset != null)
228 if (meta == null) 232 {
229 return; 233 // OK, now fetch the inside.
234 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
235 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
236 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
237 if (ids.ContainsKey(assetID))
238 ids.Remove(assetID);
239 foreach (UUID uuid in ids.Keys)
240 FetchAsset(userAssetURL, uuid);
230 241
231 // The act of gathering UUIDs downloads the assets from the remote server 242 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
232 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
233 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
234 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
235 243
244 }
245 else
246 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
236 } 247 }
237 248
238 249
@@ -246,23 +257,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
246 if (asset != null) 257 if (asset != null)
247 { 258 {
248 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 259 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
249 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 260 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
250 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 261 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
251 bool success = false;
252 foreach (UUID uuid in ids.Keys) 262 foreach (UUID uuid in ids.Keys)
253 { 263 {
254 asset = m_scene.AssetService.Get(uuid.ToString()); 264 asset = m_scene.AssetService.Get(uuid.ToString());
255 if (asset == null) 265 if (asset == null)
256 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
257 else 267 else
258 success = PostAsset(userAssetURL, asset); 268 PostAsset(userAssetURL, asset);
259 } 269 }
260 270
261 // maybe all pieces got there... 271 // maybe all pieces got there...
262 if (!success) 272 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
263 m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL);
264 else
265 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
266 273
267 } 274 }
268 else 275 else
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 6bb758e..cf72b58 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); 92 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
93 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 93 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
94 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); 94 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); 95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false);
96 } 96 }
97 else 97 else
98 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 98 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
@@ -263,13 +263,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
263 //} 263 //}
264 264
265 // OK, we're done fetching. Pass it up to the default RezObject 265 // OK, we're done fetching. Pass it up to the default RezObject
266 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 266 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
267 RezSelected, RemoveItem, fromTaskID, attachment); 267 RezSelected, RemoveItem, fromTaskID, attachment);
268
269 if (sog == null)
270 remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false);
271
272 return sog;
273 268
274 } 269 }
275 270
@@ -313,8 +308,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
313 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) 308 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
314 { 309 {
315 InventoryItemBase item = base.GetItem(agentID, itemID); 310 InventoryItemBase item = base.GetItem(agentID, itemID);
316 if (item == null)
317 return null;
318 311
319 string userAssetServer = string.Empty; 312 string userAssetServer = string.Empty;
320 if (IsForeignUser(agentID, out userAssetServer)) 313 if (IsForeignUser(agentID, out userAssetServer))
@@ -351,7 +344,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
351 344
352 private void ProcessInventoryForArriving(IClientAPI client) 345 private void ProcessInventoryForArriving(IClientAPI client)
353 { 346 {
354 // No-op for now, but we may need to do something for freign users inventory
355 } 347 }
356 348
357 // 349 //
@@ -398,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
398 390
399 private void ProcessInventoryForLeaving(IClientAPI client) 391 private void ProcessInventoryForLeaving(IClientAPI client)
400 { 392 {
401 // No-op for now
402 } 393 }
403 394
404 #endregion 395 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
index f55ba7e..fcb544f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
@@ -26,19 +26,32 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Runtime.Serialization; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.ScriptEngine.Shared 31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
32{ 37{
33 [Serializable] 38 public class HGUuidGatherer : UuidGatherer
34 public class ScriptException : Exception
35 { 39 {
36 public ScriptException() : base() {} 40 protected string m_assetServerURL;
37 41 protected HGAssetMapper m_assetMapper;
38 public ScriptException(string message) : base(message) {}
39 42
40 public ScriptException(string message, Exception innerException) : base(message, innerException) {} 43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
44 {
45 m_assetMapper = assMap;
46 m_assetServerURL = assetServerURL;
47 }
41 48
42 public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} 49 protected override AssetBase GetAsset(UUID uuid)
50 {
51 if (string.Empty == m_assetServerURL)
52 return m_assetCache.Get(uuid.ToString());
53 else
54 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
55 }
43 } 56 }
44} \ No newline at end of file 57}
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index e411585..e135c21 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
95 { 95 {
96 foreach (IMonitor monitor in m_staticMonitors) 96 foreach (IMonitor monitor in m_staticMonitors)
97 { 97 {
98 MainConsole.Instance.OutputFormat( 98 m_log.InfoFormat(
99 "[MONITOR MODULE]: {0} reports {1} = {2}", 99 "[MONITOR MODULE]: {0} reports {1} = {2}",
100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); 100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
101 } 101 }
102 102
103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) 103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
104 { 104 {
105 MainConsole.Instance.OutputFormat( 105 m_log.InfoFormat(
106 "[MONITOR MODULE]: {0} reports {1} = {2}", 106 "[MONITOR MODULE]: {0} reports {1} = {2}",
107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); 107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
108 } 108 }
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
index fd8d5e3..65e4c90 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -1,170 +1,161 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Text; 30using System.Text;
31using log4net; 31using log4net;
32 32
33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging 33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Class for writing a high performance, high volume log file. 36 /// Class for writing a high performance, high volume log file.
37 /// Sometimes, to debug, one has a high volume logging to do and the regular 37 /// Sometimes, to debug, one has a high volume logging to do and the regular
38 /// log file output is not appropriate. 38 /// log file output is not appropriate.
39 /// Create a new instance with the parameters needed and 39 /// Create a new instance with the parameters needed and
40 /// call Write() to output a line. Call Close() when finished. 40 /// call Write() to output a line. Call Close() when finished.
41 /// If created with no parameters, it will not log anything. 41 /// If created with no parameters, it will not log anything.
42 /// </summary> 42 /// </summary>
43 public class LogWriter : IDisposable 43 public class LogWriter : IDisposable
44 { 44 {
45 public bool Enabled { get; private set; } 45 public bool Enabled { get; private set; }
46 46
47 private string m_logDirectory = "."; 47 private string m_logDirectory = ".";
48 private int m_logMaxFileTimeMin = 5; // 5 minutes 48 private int m_logMaxFileTimeMin = 5; // 5 minutes
49 public String LogFileHeader { get; set; } 49 public String LogFileHeader { get; set; }
50 50
51 private StreamWriter m_logFile = null; 51 private StreamWriter m_logFile = null;
52 private TimeSpan m_logFileLife; 52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime; 53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object(); 54 private Object m_logFileWriteLock = new Object();
55 55
56 // set externally when debugging. If let 'null', this does not write any error messages. 56 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null; 57 public ILog ErrorLogger = null;
58 private string LogHeader = "[LOG WRITER]"; 58 private string LogHeader = "[LOG WRITER]";
59 59
60 /// <summary> 60 /// <summary>
61 /// Create a log writer that will not write anything. Good for when not enabled 61 /// Create a log writer that will not write anything. Good for when not enabled
62 /// but the write statements are still in the code. 62 /// but the write statements are still in the code.
63 /// </summary> 63 /// </summary>
64 public LogWriter() 64 public LogWriter()
65 { 65 {
66 Enabled = false; 66 Enabled = false;
67 m_logFile = null; 67 m_logFile = null;
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Create a log writer instance. 71 /// Create a log writer instance.
72 /// </summary> 72 /// </summary>
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> 73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> 74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> 75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime) 76 public LogWriter(string dir, string headr, int maxFileTime)
77 { 77 {
78 m_logDirectory = dir == null ? "." : dir; 78 m_logDirectory = dir == null ? "." : dir;
79 79
80 LogFileHeader = headr == null ? "log-" : headr; 80 LogFileHeader = headr == null ? "log-" : headr;
81 81
82 m_logMaxFileTimeMin = maxFileTime; 82 m_logMaxFileTimeMin = maxFileTime;
83 if (m_logMaxFileTimeMin < 1) 83 if (m_logMaxFileTimeMin < 1)
84 m_logMaxFileTimeMin = 5; 84 m_logMaxFileTimeMin = 5;
85 85
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); 86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife; 87 m_logFileEndTime = DateTime.Now + m_logFileLife;
88 88
89 Enabled = true; 89 Enabled = true;
90 } 90 }
91 91
92 public void Dispose() 92 public void Dispose()
93 { 93 {
94 this.Close(); 94 this.Close();
95 } 95 }
96 96
97 public void Close() 97 public void Close()
98 { 98 {
99 Enabled = false; 99 Enabled = false;
100 if (m_logFile != null) 100 if (m_logFile != null)
101 { 101 {
102 m_logFile.Close(); 102 m_logFile.Close();
103 m_logFile.Dispose(); 103 m_logFile.Dispose();
104 m_logFile = null; 104 m_logFile = null;
105 } 105 }
106 } 106 }
107 107
108 public void Write(string line, params object[] args) 108 public void Write(string line, params object[] args)
109 { 109 {
110 if (!Enabled) return; 110 if (!Enabled) return;
111 Write(String.Format(line, args)); 111 Write(String.Format(line, args));
112 } 112 }
113 113
114 public void Flush() 114 public void Write(string line)
115 { 115 {
116 if (!Enabled) return; 116 if (!Enabled) return;
117 if (m_logFile != null) 117 try
118 { 118 {
119 m_logFile.Flush(); 119 lock (m_logFileWriteLock)
120 } 120 {
121 } 121 DateTime now = DateTime.Now;
122 122 if (m_logFile == null || now > m_logFileEndTime)
123 public void Write(string line) 123 {
124 { 124 if (m_logFile != null)
125 if (!Enabled) return; 125 {
126 try 126 m_logFile.Close();
127 { 127 m_logFile.Dispose();
128 lock (m_logFileWriteLock) 128 m_logFile = null;
129 { 129 }
130 DateTime now = DateTime.Now; 130
131 if (m_logFile == null || now > m_logFileEndTime) 131 // First log file or time has expired, start writing to a new log file
132 { 132 m_logFileEndTime = now + m_logFileLife;
133 if (m_logFile != null) 133 string path = (m_logDirectory.Length > 0 ? m_logDirectory
134 { 134 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
135 m_logFile.Close(); 135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
136 m_logFile.Dispose(); 136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
137 m_logFile = null; 137 }
138 } 138 if (m_logFile != null)
139 139 {
140 // First log file or time has expired, start writing to a new log file 140 StringBuilder buff = new StringBuilder(line.Length + 25);
141 m_logFileEndTime = now + m_logFileLife; 141 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
142 string path = (m_logDirectory.Length > 0 ? m_logDirectory 142 // buff.Append(now.ToString("yyyyMMddHHmmss"));
143 + System.IO.Path.DirectorySeparatorChar.ToString() : "") 143 buff.Append(",");
144 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); 144 buff.Append(line);
145 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); 145 buff.Append("\r\n");
146 } 146 m_logFile.Write(buff.ToString());
147 if (m_logFile != null) 147 }
148 { 148 }
149 StringBuilder buff = new StringBuilder(line.Length + 25); 149 }
150 buff.Append(now.ToString("yyyyMMddHHmmssfff")); 150 catch (Exception e)
151 // buff.Append(now.ToString("yyyyMMddHHmmss")); 151 {
152 buff.Append(","); 152 if (ErrorLogger != null)
153 buff.Append(line); 153 {
154 buff.Append("\r\n"); 154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
155 m_logFile.Write(buff.ToString()); 155 }
156 } 156 Enabled = false;
157 } 157 }
158 } 158 return;
159 catch (Exception e) 159 }
160 { 160 }
161 if (ErrorLogger != null) 161} \ No newline at end of file
162 {
163 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
164 }
165 Enabled = false;
166 }
167 return;
168 }
169 }
170}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index acefc97..4eecaa2 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -137,9 +137,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
137 ud.FirstName = words[0]; 137 ud.FirstName = words[0];
138 ud.LastName = "@" + words[1]; 138 ud.LastName = "@" + words[1];
139 users.Add(ud); 139 users.Add(ud);
140 // WARNING! that uriStr is not quite right... it may be missing the / at the end,
141 // which will cause trouble (duplicate entries on some tables). We should
142 // get the UUI instead from the UAS. TO BE FIXED.
143 AddUser(userID, names[0], names[1], uriStr); 140 AddUser(userID, names[0], names[1], uriStr);
144 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); 141 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
145 } 142 }
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index b4811da..f4ed67b 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -31,7 +31,6 @@ using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Console; 33using OpenSim.Framework.Console;
34using OpenSim.Region.ClientStack.LindenUDP;
35using OpenSim.Region.Framework; 34using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
@@ -430,7 +429,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
430 429
431 public void AddUser(UUID uuid, string first, string last, string homeURL) 430 public void AddUser(UUID uuid, string first, string last, string homeURL)
432 { 431 {
433 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 432 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
433
434 AddUser(uuid, homeURL + ";" + first + " " + last); 434 AddUser(uuid, homeURL + ";" + first + " " + last);
435 } 435 }
436 436
@@ -553,8 +553,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
553 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 553 MainConsole.Instance.Output("-----------------------------------------------------------------------------");
554 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 554 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
555 { 555 {
556 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", 556 MainConsole.Instance.Output(String.Format("{0} {1} {2}",
557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); 557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
558 } 558 }
559 559
560 return; 560 return;
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index 6c73d91..424e0ab 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -15,7 +15,6 @@
15 <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" /> 15 <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" />
16 <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" /> 16 <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" />
17 <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" /> 17 <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" />
18 <RegionModule id="DwellModule" type="OpenSim.Region.CoreModules.World.Land.DwellModule" />
19 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" /> 18 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" />
20 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" /> 19 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" />
21 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" /> 20 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" />
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
deleted file mode 100644
index fce9490..0000000
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
+++ /dev/null
@@ -1,61 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 93a045e..18bd018 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,29 +42,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int ALL_SIDES = -1; 47 private const int ALL_SIDES = -1;
48 48
49 public const int DISP_EXPIRE = 1; 49 public const int DISP_EXPIRE = 1;
50 public const int DISP_TEMP = 2; 50 public const int DISP_TEMP = 2;
51 51
52 /// <summary>
53 /// If true then where possible dynamic textures are reused.
54 /// </summary>
55 public bool ReuseTextures { get; set; }
56
57 /// <summary>
58 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
59 /// </summary>
60 /// <remarks>
61 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
62 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
63 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
64 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
65 /// to work around this problem.</remarks>
66 public bool ReuseLowDataTextures { get; set; }
67
68 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
69 53
70 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 54 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -72,15 +56,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
72 56
73 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
74 58
75 /// <summary>
76 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
77 /// regenerate.
78 /// </summary>
79 /// <remarks>
80 /// Key is string.Format("{0}{1}", data
81 /// </remarks>
82 private Cache m_reuseableDynamicTextures;
83
84 #region IDynamicTextureManager Members 59 #region IDynamicTextureManager Members
85 60
86 public void RegisterRender(string handleType, IDynamicTextureRender render) 61 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -94,17 +69,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
94 /// <summary> 69 /// <summary>
95 /// Called by code which actually renders the dynamic texture to supply texture data. 70 /// Called by code which actually renders the dynamic texture to supply texture data.
96 /// </summary> 71 /// </summary>
97 /// <param name="updaterId"></param> 72 /// <param name="id"></param>
98 /// <param name="texture"></param> 73 /// <param name="data"></param>
99 public void ReturnData(UUID updaterId, IDynamicTexture texture) 74 public void ReturnData(UUID id, byte[] data)
100 { 75 {
101 DynamicTextureUpdater updater = null; 76 DynamicTextureUpdater updater = null;
102 77
103 lock (Updaters) 78 lock (Updaters)
104 { 79 {
105 if (Updaters.ContainsKey(updaterId)) 80 if (Updaters.ContainsKey(id))
106 { 81 {
107 updater = Updaters[updaterId]; 82 updater = Updaters[id];
108 } 83 }
109 } 84 }
110 85
@@ -113,16 +88,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
113 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 88 if (RegisteredScenes.ContainsKey(updater.SimUUID))
114 { 89 {
115 Scene scene = RegisteredScenes[updater.SimUUID]; 90 Scene scene = RegisteredScenes[updater.SimUUID];
116 UUID newTextureID = updater.DataReceived(texture.Data, scene); 91 updater.DataReceived(data, scene);
117
118 if (ReuseTextures
119 && !updater.BlendWithOldTexture
120 && texture.IsReuseable
121 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
122 {
123 m_reuseableDynamicTextures.Store(
124 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
125 }
126 } 92 }
127 } 93 }
128 94
@@ -138,27 +104,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
138 } 104 }
139 } 105 }
140 106
141 /// <summary>
142 /// Determines whether the texture is reuseable based on its data size.
143 /// </summary>
144 /// <remarks>
145 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
146 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
147 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
148 /// </remarks>
149 /// <returns></returns>
150 private bool IsDataSizeReuseable(IDynamicTexture texture)
151 {
152// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
153 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
154
155// m_log.DebugFormat(
156// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
157// discardLevel2DataThreshold, texture.Data.Length);
158
159 return discardLevel2DataThreshold < texture.Data.Length;
160 }
161
162 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
163 string extraParams, int updateTimer) 108 string extraParams, int updateTimer)
164 { 109 {
@@ -222,61 +167,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
222 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
223 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
224 { 169 {
225 if (!RenderPlugins.ContainsKey(contentType)) 170 if (RenderPlugins.ContainsKey(contentType))
226 return UUID.Zero;
227
228 Scene scene;
229 RegisteredScenes.TryGetValue(simID, out scene);
230
231 if (scene == null)
232 return UUID.Zero;
233
234 SceneObjectPart part = scene.GetSceneObjectPart(primID);
235
236 if (part == null)
237 return UUID.Zero;
238
239 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
240 // them.
241 if (ReuseTextures)
242 disp = disp & ~DISP_EXPIRE;
243
244 DynamicTextureUpdater updater = new DynamicTextureUpdater();
245 updater.SimUUID = simID;
246 updater.PrimID = primID;
247 updater.ContentType = contentType;
248 updater.BodyData = data;
249 updater.UpdateTimer = updateTimer;
250 updater.UpdaterID = UUID.Random();
251 updater.Params = extraParams;
252 updater.BlendWithOldTexture = SetBlending;
253 updater.FrontAlpha = AlphaValue;
254 updater.Face = face;
255 updater.Url = "Local image";
256 updater.Disp = disp;
257
258 object objReusableTextureUUID = null;
259
260 if (ReuseTextures && !updater.BlendWithOldTexture)
261 { 171 {
262 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); 172 DynamicTextureUpdater updater = new DynamicTextureUpdater();
263 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); 173 updater.SimUUID = simID;
264 174 updater.PrimID = primID;
265 if (objReusableTextureUUID != null) 175 updater.ContentType = contentType;
266 { 176 updater.BodyData = data;
267 // If something else has removed this temporary asset from the cache, detect and invalidate 177 updater.UpdateTimer = updateTimer;
268 // our cached uuid. 178 updater.UpdaterID = UUID.Random();
269 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) 179 updater.Params = extraParams;
270 { 180 updater.BlendWithOldTexture = SetBlending;
271 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); 181 updater.FrontAlpha = AlphaValue;
272 objReusableTextureUUID = null; 182 updater.Face = face;
273 } 183 updater.Url = "Local image";
274 } 184 updater.Disp = disp;
275 }
276 185
277 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
278 if (objReusableTextureUUID == null)
279 {
280 lock (Updaters) 186 lock (Updaters)
281 { 187 {
282 if (!Updaters.ContainsKey(updater.UpdaterID)) 188 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -285,29 +191,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
285 } 191 }
286 } 192 }
287 193
288// m_log.DebugFormat(
289// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
290// part.Name, part.ParentGroup.Scene.Name);
291
292 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
293 } 196 }
294 else 197
295 { 198 return UUID.Zero;
296// m_log.DebugFormat(
297// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
298// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
299
300 // No need to add to updaters as the texture is always the same. Not that this functionality
301 // apppears to be implemented anyway.
302 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
303 }
304
305 return updater.UpdaterID;
306 }
307
308 private string GenerateReusableTextureKey(string data, string extraParams)
309 {
310 return string.Format("{0}{1}", data, extraParams);
311 } 199 }
312 200
313 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -327,13 +215,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
327 215
328 public void Initialise(Scene scene, IConfigSource config) 216 public void Initialise(Scene scene, IConfigSource config)
329 { 217 {
330 IConfig texturesConfig = config.Configs["Textures"];
331 if (texturesConfig != null)
332 {
333 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
334 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
335 }
336
337 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
338 { 219 {
339 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); 220 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
@@ -343,11 +224,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
343 224
344 public void PostInitialise() 225 public void PostInitialise()
345 { 226 {
346 if (ReuseTextures)
347 {
348 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
349 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
350 }
351 } 227 }
352 228
353 public void Close() 229 public void Close()
@@ -393,60 +269,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
393 } 269 }
394 270
395 /// <summary> 271 /// <summary>
396 /// Update the given part with the new texture.
397 /// </summary>
398 /// <returns>
399 /// The old texture UUID.
400 /// </returns>
401 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
402 {
403 UUID oldID;
404
405 lock (part)
406 {
407 // mostly keep the values from before
408 Primitive.TextureEntry tmptex = part.Shape.Textures;
409
410 // FIXME: Need to return the appropriate ID if only a single face is replaced.
411 oldID = tmptex.DefaultTexture.TextureID;
412
413 if (Face == ALL_SIDES)
414 {
415 oldID = tmptex.DefaultTexture.TextureID;
416 tmptex.DefaultTexture.TextureID = textureID;
417 }
418 else
419 {
420 try
421 {
422 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
423 texface.TextureID = textureID;
424 tmptex.FaceTextures[Face] = texface;
425 }
426 catch (Exception)
427 {
428 tmptex.DefaultTexture.TextureID = textureID;
429 }
430 }
431
432 // I'm pretty sure we always want to force this to true
433 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
434 // tmptex.DefaultTexture.Fullbright = true;
435
436 part.UpdateTextureEntry(tmptex.GetBytes());
437 }
438
439 return oldID;
440 }
441
442 /// <summary>
443 /// Called once new texture data has been received for this updater. 272 /// Called once new texture data has been received for this updater.
444 /// </summary> 273 /// </summary>
445 /// <param name="data"></param> 274 public void DataReceived(byte[] data, Scene scene)
446 /// <param name="scene"></param>
447 /// <param name="isReuseable">True if the data given is reuseable.</param>
448 /// <returns>The asset UUID given to the incoming data.</returns>
449 public UUID DataReceived(byte[] data, Scene scene)
450 { 275 {
451 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
452 277
@@ -456,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
456 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
457 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
458 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
459 284 return;
460 return UUID.Zero;
461 } 285 }
462 286
463 byte[] assetData = null; 287 byte[] assetData = null;
@@ -495,29 +319,56 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
495 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
496 if (cacheLayerDecode != null) 320 if (cacheLayerDecode != null)
497 { 321 {
498 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) 322 cacheLayerDecode.Decode(asset.FullID, asset.Data);
499 m_log.WarnFormat( 323 cacheLayerDecode = null;
500 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
501 asset.ID, part.Name, part.ParentGroup.Scene.Name);
502 } 324 }
503 325
504 UUID oldID = UpdatePart(part, asset.FullID); 326 UUID oldID = UUID.Zero;
505 327
506 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 328 lock (part)
507 { 329 {
508 if (oldAsset == null) 330 // mostly keep the values from before
509 oldAsset = scene.AssetService.Get(oldID.ToString()); 331 Primitive.TextureEntry tmptex = part.Shape.Textures;
332
333 // remove the old asset from the cache
334 oldID = tmptex.DefaultTexture.TextureID;
335
336 if (Face == ALL_SIDES)
337 {
338 tmptex.DefaultTexture.TextureID = asset.FullID;
339 }
340 else
341 {
342 try
343 {
344 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
345 texface.TextureID = asset.FullID;
346 tmptex.FaceTextures[Face] = texface;
347 }
348 catch (Exception)
349 {
350 tmptex.DefaultTexture.TextureID = asset.FullID;
351 }
352 }
510 353
354 // I'm pretty sure we always want to force this to true
355 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
356 // tmptex.DefaultTexture.Fullbright = true;
357
358 part.UpdateTextureEntry(tmptex.GetBytes());
359 }
360
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
511 if (oldAsset != null) 364 if (oldAsset != null)
512 { 365 {
513 if (oldAsset.Temporary) 366 if (oldAsset.Temporary == true)
514 { 367 {
515 scene.AssetService.Delete(oldID.ToString()); 368 scene.AssetService.Delete(oldID.ToString());
516 } 369 }
517 } 370 }
518 } 371 }
519
520 return asset.FullID;
521 } 372 }
522 373
523 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 0b9174f..56221aa 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -58,7 +58,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
58 public string body; 58 public string body;
59 public int responseCode; 59 public int responseCode;
60 public string responseBody; 60 public string responseBody;
61 public string responseType = "text/plain";
62 //public ManualResetEvent ev; 61 //public ManualResetEvent ev;
63 public bool requestDone; 62 public bool requestDone;
64 public int startTime; 63 public int startTime;
@@ -271,22 +270,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
271 } 270 }
272 } 271 }
273 272
274 public void HttpContentType(UUID request, string type)
275 {
276 lock (m_UrlMap)
277 {
278 if (m_RequestMap.ContainsKey(request))
279 {
280 UrlData urlData = m_RequestMap[request];
281 urlData.requests[request].responseType = type;
282 }
283 else
284 {
285 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
286 }
287 }
288 }
289
290 public void HttpResponse(UUID request, int status, string body) 273 public void HttpResponse(UUID request, int status, string body)
291 { 274 {
292 lock (m_RequestMap) 275 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 45e6527..6f83948 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,7 +32,6 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
38using log4net; 37using log4net;
@@ -68,18 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
68 return true; 67 return true;
69 } 68 }
70 69
71// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) 70 public byte[] ConvertUrl(string url, string extraParams)
72// {
73// // We don't support conversion of body data.
74// return false;
75// }
76
77 public IDynamicTexture ConvertUrl(string url, string extraParams)
78 { 71 {
79 return null; 72 return null;
80 } 73 }
81 74
82 public IDynamicTexture ConvertData(string bodyData, string extraParams) 75 public byte[] ConvertStream(Stream data, string extraParams)
83 { 76 {
84 return null; 77 return null;
85 } 78 }
@@ -172,11 +165,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
172 165
173 private void HttpRequestReturn(IAsyncResult result) 166 private void HttpRequestReturn(IAsyncResult result)
174 { 167 {
168
175 RequestState state = (RequestState) result.AsyncState; 169 RequestState state = (RequestState) result.AsyncState;
176 WebRequest request = (WebRequest) state.Request; 170 WebRequest request = (WebRequest) state.Request;
177 Stream stream = null; 171 Stream stream = null;
178 byte[] imageJ2000 = new byte[0]; 172 byte[] imageJ2000 = new byte[0];
179 Size newSize = new Size(0, 0);
180 173
181 try 174 try
182 { 175 {
@@ -189,43 +182,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
189 try 182 try
190 { 183 {
191 Bitmap image = new Bitmap(stream); 184 Bitmap image = new Bitmap(stream);
185 Size newsize;
192 186
193 // TODO: make this a bit less hard coded 187 // TODO: make this a bit less hard coded
194 if ((image.Height < 64) && (image.Width < 64)) 188 if ((image.Height < 64) && (image.Width < 64))
195 { 189 {
196 newSize.Width = 32; 190 newsize = new Size(32, 32);
197 newSize.Height = 32;
198 } 191 }
199 else if ((image.Height < 128) && (image.Width < 128)) 192 else if ((image.Height < 128) && (image.Width < 128))
200 { 193 {
201 newSize.Width = 64; 194 newsize = new Size(64, 64);
202 newSize.Height = 64;
203 } 195 }
204 else if ((image.Height < 256) && (image.Width < 256)) 196 else if ((image.Height < 256) && (image.Width < 256))
205 { 197 {
206 newSize.Width = 128; 198 newsize = new Size(128, 128);
207 newSize.Height = 128;
208 } 199 }
209 else if ((image.Height < 512 && image.Width < 512)) 200 else if ((image.Height < 512 && image.Width < 512))
210 { 201 {
211 newSize.Width = 256; 202 newsize = new Size(256, 256);
212 newSize.Height = 256;
213 } 203 }
214 else if ((image.Height < 1024 && image.Width < 1024)) 204 else if ((image.Height < 1024 && image.Width < 1024))
215 { 205 {
216 newSize.Width = 512; 206 newsize = new Size(512, 512);
217 newSize.Height = 512;
218 } 207 }
219 else 208 else
220 { 209 {
221 newSize.Width = 1024; 210 newsize = new Size(1024, 1024);
222 newSize.Height = 1024;
223 } 211 }
224 212
225 using (Bitmap resize = new Bitmap(image, newSize)) 213 Bitmap resize = new Bitmap(image, newsize);
226 { 214
227 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
228 }
229 } 216 }
230 catch (Exception) 217 catch (Exception)
231 { 218 {
@@ -240,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
240 } 227 }
241 catch (WebException) 228 catch (WebException)
242 { 229 {
230
243 } 231 }
244 finally 232 finally
245 { 233 {
@@ -248,14 +236,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
248 stream.Close(); 236 stream.Close();
249 } 237 }
250 } 238 }
251 239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
252 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
253 imageJ2000.Length, state.RequestID); 240 imageJ2000.Length, state.RequestID);
254 241 m_textureManager.ReturnData(state.RequestID, imageJ2000);
255 m_textureManager.ReturnData(
256 state.RequestID,
257 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
258 request.RequestUri, null, imageJ2000, newSize, false));
259 } 242 }
260 243
261 #region Nested type: RequestState 244 #region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 41baccc..9787c8c 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,292 +45,31 @@ using OpenSim.Tests.Common.Mock;
45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
46{ 46{
47 [TestFixture] 47 [TestFixture]
48 public class VectorRenderModuleTests : OpenSimTestCase 48 public class VectorRenderModuleTests
49 { 49 {
50 Scene m_scene;
51 DynamicTextureModule m_dtm;
52 VectorRenderModule m_vrm;
53
54 private void SetupScene(bool reuseTextures)
55 {
56 m_scene = new SceneHelpers().SetupScene();
57
58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
61
62 m_vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
65 }
66
67 [Test] 50 [Test]
68 public void TestDraw() 51 public void TestDraw()
69 { 52 {
70 TestHelpers.InMethod(); 53 TestHelpers.InMethod();
71 54
72 SetupScene(false); 55 Scene scene = new SceneHelpers().SetupScene();
73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 56 DynamicTextureModule dtm = new DynamicTextureModule();
74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 57 VectorRenderModule vrm = new VectorRenderModule();
75 58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
76 m_dtm.AddDynamicTextureData(
77 m_scene.RegionInfo.RegionID,
78 so.UUID,
79 m_vrm.GetContentType(),
80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
81 "",
82 0);
83
84 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
85 }
86
87 [Test]
88 public void TestRepeatSameDraw()
89 {
90 TestHelpers.InMethod();
91
92 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
93
94 SetupScene(false);
95 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
96
97 m_dtm.AddDynamicTextureData(
98 m_scene.RegionInfo.RegionID,
99 so.UUID,
100 m_vrm.GetContentType(),
101 dtText,
102 "",
103 0);
104
105 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
106
107 m_dtm.AddDynamicTextureData(
108 m_scene.RegionInfo.RegionID,
109 so.UUID,
110 m_vrm.GetContentType(),
111 dtText,
112 "",
113 0);
114
115 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
116 }
117
118 [Test]
119 public void TestRepeatSameDrawDifferentExtraParams()
120 {
121 TestHelpers.InMethod();
122
123 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
124
125 SetupScene(false);
126 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
127
128 m_dtm.AddDynamicTextureData(
129 m_scene.RegionInfo.RegionID,
130 so.UUID,
131 m_vrm.GetContentType(),
132 dtText,
133 "",
134 0);
135
136 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
137
138 m_dtm.AddDynamicTextureData(
139 m_scene.RegionInfo.RegionID,
140 so.UUID,
141 m_vrm.GetContentType(),
142 dtText,
143 "alpha:250",
144 0);
145
146 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
147 }
148
149 [Test]
150 public void TestRepeatSameDrawContainingImage()
151 {
152 TestHelpers.InMethod();
153
154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
156
157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
159
160 m_dtm.AddDynamicTextureData(
161 m_scene.RegionInfo.RegionID,
162 so.UUID,
163 m_vrm.GetContentType(),
164 dtText,
165 "",
166 0);
167
168 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
169
170 m_dtm.AddDynamicTextureData(
171 m_scene.RegionInfo.RegionID,
172 so.UUID,
173 m_vrm.GetContentType(),
174 dtText,
175 "",
176 0);
177
178 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
179 }
180
181 [Test]
182 public void TestDrawReusingTexture()
183 {
184 TestHelpers.InMethod();
185 59
186 SetupScene(true); 60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189 62
190 m_dtm.AddDynamicTextureData( 63 dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID, 64 scene.RegionInfo.RegionID,
192 so.UUID, 65 so.UUID,
193 m_vrm.GetContentType(), 66 vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "", 68 "",
196 0); 69 0);
197 70
198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
199 }
200
201 [Test]
202 public void TestRepeatSameDrawReusingTexture()
203 {
204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
206
207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
208
209 SetupScene(true);
210 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
211
212 m_dtm.AddDynamicTextureData(
213 m_scene.RegionInfo.RegionID,
214 so.UUID,
215 m_vrm.GetContentType(),
216 dtText,
217 "",
218 0);
219
220 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
221
222 m_dtm.AddDynamicTextureData(
223 m_scene.RegionInfo.RegionID,
224 so.UUID,
225 m_vrm.GetContentType(),
226 dtText,
227 "",
228 0);
229
230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
231 }
232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
273 [Test]
274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
275 {
276 TestHelpers.InMethod();
277
278 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
279
280 SetupScene(true);
281 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
282
283 m_dtm.AddDynamicTextureData(
284 m_scene.RegionInfo.RegionID,
285 so.UUID,
286 m_vrm.GetContentType(),
287 dtText,
288 "",
289 0);
290
291 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
292
293 m_dtm.AddDynamicTextureData(
294 m_scene.RegionInfo.RegionID,
295 so.UUID,
296 m_vrm.GetContentType(),
297 dtText,
298 "alpha:250",
299 0);
300
301 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
302 }
303
304 [Test]
305 public void TestRepeatSameDrawContainingImageReusingTexture()
306 {
307 TestHelpers.InMethod();
308
309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
311
312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
314
315 m_dtm.AddDynamicTextureData(
316 m_scene.RegionInfo.RegionID,
317 so.UUID,
318 m_vrm.GetContentType(),
319 dtText,
320 "",
321 0);
322
323 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
324
325 m_dtm.AddDynamicTextureData(
326 m_scene.RegionInfo.RegionID,
327 so.UUID,
328 m_vrm.GetContentType(),
329 dtText,
330 "",
331 0);
332 71
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 } 73 }
335 } 74 }
336} \ No newline at end of file 75} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 673c2d1..8b2f2f8 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,12 +30,10 @@ using System.Drawing;
30using System.Drawing.Imaging; 30using System.Drawing.Imaging;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Linq;
34using System.Net; 33using System.Net;
35using Nini.Config; 34using Nini.Config;
36using OpenMetaverse; 35using OpenMetaverse;
37using OpenMetaverse.Imaging; 36using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
39using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
41using log4net; 39using log4net;
@@ -47,13 +45,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
47{ 45{
48 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
49 { 47 {
50 // These fields exist for testing purposes, please do not remove.
51// private static bool s_flipper;
52// private static byte[] s_asset1Data;
53// private static byte[] s_asset2Data;
54
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 49
50 private string m_name = "VectorRenderModule";
57 private Scene m_scene; 51 private Scene m_scene;
58 private IDynamicTextureManager m_textureManager; 52 private IDynamicTextureManager m_textureManager;
59 private Graphics m_graph; 53 private Graphics m_graph;
@@ -67,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
67 61
68 public string GetContentType() 62 public string GetContentType()
69 { 63 {
70 return "vector"; 64 return ("vector");
71 } 65 }
72 66
73 public string GetName() 67 public string GetName()
74 { 68 {
75 return Name; 69 return m_name;
76 } 70 }
77 71
78 public bool SupportsAsynchronous() 72 public bool SupportsAsynchronous()
@@ -80,20 +74,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
80 return true; 74 return true;
81 } 75 }
82 76
83// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) 77 public byte[] ConvertUrl(string url, string extraParams)
84// {
85// string[] lines = GetLines(bodyData);
86// return lines.Any((str, r) => str.StartsWith("Image"));
87// }
88
89 public IDynamicTexture ConvertUrl(string url, string extraParams)
90 { 78 {
91 return null; 79 return null;
92 } 80 }
93 81
94 public IDynamicTexture ConvertData(string bodyData, string extraParams) 82 public byte[] ConvertStream(Stream data, string extraParams)
95 { 83 {
96 return Draw(bodyData, extraParams); 84 return null;
97 } 85 }
98 86
99 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 87 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -103,28 +91,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
103 91
104 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
105 { 93 {
106 // XXX: This isn't actually being done asynchronously! 94 Draw(bodyData, id, extraParams);
107 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
108
109 return true; 95 return true;
110 } 96 }
111 97
112 public void GetDrawStringSize(string text, string fontName, int fontSize, 98 public void GetDrawStringSize(string text, string fontName, int fontSize,
113 out double xSize, out double ySize) 99 out double xSize, out double ySize)
114 { 100 {
115 lock (this) 101 using (Font myFont = new Font(fontName, fontSize))
116 { 102 {
117 using (Font myFont = new Font(fontName, fontSize)) 103 SizeF stringSize = new SizeF();
104 lock (m_graph)
118 { 105 {
119 SizeF stringSize = new SizeF(); 106 stringSize = m_graph.MeasureString(text, myFont);
120 107 xSize = stringSize.Width;
121 // XXX: This lock may be unnecessary. 108 ySize = stringSize.Height;
122 lock (m_graph)
123 {
124 stringSize = m_graph.MeasureString(text, myFont);
125 xSize = stringSize.Width;
126 ySize = stringSize.Height;
127 }
128 } 109 }
129 } 110 }
130 } 111 }
@@ -163,13 +144,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
163 { 144 {
164 m_textureManager.RegisterRender(GetContentType(), this); 145 m_textureManager.RegisterRender(GetContentType(), this);
165 } 146 }
166
167 // This code exists for testing purposes, please do not remove.
168// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
169// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
170
171 // Terrain dirt - smallest bin/assets file (6004 bytes)
172// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
173 } 147 }
174 148
175 public void Close() 149 public void Close()
@@ -178,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
178 152
179 public string Name 153 public string Name
180 { 154 {
181 get { return "VectorRenderModule"; } 155 get { return m_name; }
182 } 156 }
183 157
184 public bool IsSharedModule 158 public bool IsSharedModule
@@ -188,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
188 162
189 #endregion 163 #endregion
190 164
191 private IDynamicTexture Draw(string data, string extraParams) 165 private void Draw(string data, UUID id, string extraParams)
192 { 166 {
193 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 167 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
194 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -331,57 +305,40 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
331 305
332 Bitmap bitmap = null; 306 Bitmap bitmap = null;
333 Graphics graph = null; 307 Graphics graph = null;
334 bool reuseable = false;
335 308
336 try 309 try
337 { 310 {
338 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, 311 if (alpha == 256)
339 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to 312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
340 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were 313 else
341 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed 314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
342 // under lock. 315
343 lock (this) 316 graph = Graphics.FromImage(bitmap);
344 {
345 if (alpha == 256)
346 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
347 else
348 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
349 317
350 graph = Graphics.FromImage(bitmap); 318 // this is really just to save people filling the
351 319 // background color in their scripts, only do when fully opaque
352 // this is really just to save people filling the 320 if (alpha >= 255)
353 // background color in their scripts, only do when fully opaque 321 {
354 if (alpha >= 255) 322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
355 { 323 {
356 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 324 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
357 {
358 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
359 }
360 } 325 }
361 326 }
362 for (int w = 0; w < bitmap.Width; w++) 327
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
363 { 331 {
364 if (alpha <= 255) 332 for (int h = 0; h < bitmap.Height; h++)
365 { 333 {
366 for (int h = 0; h < bitmap.Height; h++) 334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
367 {
368 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
369 }
370 } 335 }
371 } 336 }
372
373 GDIDraw(data, graph, altDataDelim, out reuseable);
374 } 337 }
375 338
339 GDIDraw(data, graph, altDataDelim);
340
376 byte[] imageJ2000 = new byte[0]; 341 byte[] imageJ2000 = new byte[0];
377
378 // This code exists for testing purposes, please do not remove.
379// if (s_flipper)
380// imageJ2000 = s_asset1Data;
381// else
382// imageJ2000 = s_asset2Data;
383//
384// s_flipper = !s_flipper;
385 342
386 try 343 try
387 { 344 {
@@ -394,24 +351,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
394 e.Message, e.StackTrace); 351 e.Message, e.StackTrace);
395 } 352 }
396 353
397 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( 354 m_textureManager.ReturnData(id, imageJ2000);
398 data, extraParams, imageJ2000, new Size(width, height), reuseable);
399 } 355 }
400 finally 356 finally
401 { 357 {
402 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, 358 if (graph != null)
403 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to 359 graph.Dispose();
404 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were 360
405 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed 361 if (bitmap != null)
406 // under lock. 362 bitmap.Dispose();
407 lock (this)
408 {
409 if (graph != null)
410 graph.Dispose();
411
412 if (bitmap != null)
413 bitmap.Dispose();
414 }
415 } 363 }
416 } 364 }
417 365
@@ -470,21 +418,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
470 } 418 }
471*/ 419*/
472 420
473 /// <summary> 421 private void GDIDraw(string data, Graphics graph, char dataDelim)
474 /// Split input data into discrete command lines.
475 /// </summary>
476 /// <returns></returns>
477 /// <param name='data'></param>
478 /// <param name='dataDelim'></param>
479 private string[] GetLines(string data, char dataDelim)
480 {
481 char[] lineDelimiter = { dataDelim };
482 return data.Split(lineDelimiter);
483 }
484
485 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
486 { 422 {
487 reuseable = true;
488 Point startPoint = new Point(0, 0); 423 Point startPoint = new Point(0, 0);
489 Point endPoint = new Point(0, 0); 424 Point endPoint = new Point(0, 0);
490 Pen drawPen = null; 425 Pen drawPen = null;
@@ -499,9 +434,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
499 myFont = new Font(fontName, fontSize); 434 myFont = new Font(fontName, fontSize);
500 myBrush = new SolidBrush(Color.Black); 435 myBrush = new SolidBrush(Color.Black);
501 436
437 char[] lineDelimiter = {dataDelim};
502 char[] partsDelimiter = {','}; 438 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
503 440
504 foreach (string line in GetLines(data, dataDelim)) 441 foreach (string line in lines)
505 { 442 {
506 string nextLine = line.Trim(); 443 string nextLine = line.Trim();
507 //replace with switch, or even better, do some proper parsing 444 //replace with switch, or even better, do some proper parsing
@@ -532,10 +469,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
532 } 469 }
533 else if (nextLine.StartsWith("Image")) 470 else if (nextLine.StartsWith("Image"))
534 { 471 {
535 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
536 // can change.
537 reuseable = false;
538
539 float x = 0; 472 float x = 0;
540 float y = 0; 473 float y = 0;
541 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index e167e31..07bb291 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -28,7 +28,6 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32using Nini.Config; 31using Nini.Config;
33using OpenMetaverse; 32using OpenMetaverse;
34using OpenSim.Framework; 33using OpenSim.Framework;
@@ -173,42 +172,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
173 /// <param name="hostID">UUID of the SceneObjectPart</param> 172 /// <param name="hostID">UUID of the SceneObjectPart</param>
174 /// <param name="channel">channel to listen on</param> 173 /// <param name="channel">channel to listen on</param>
175 /// <param name="name">name to filter on</param> 174 /// <param name="name">name to filter on</param>
176 /// <param name="id"> 175 /// <param name="id">key to filter on (user given, could be totally faked)</param>
177 /// key to filter on (user given, could be totally faked)
178 /// </param>
179 /// <param name="msg">msg to filter on</param>
180 /// <returns>number of the scripts handle</returns>
181 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
182 string name, UUID id, string msg)
183 {
184 return m_listenerManager.AddListener(localID, itemID, hostID,
185 channel, name, id, msg);
186 }
187
188 /// <summary>
189 /// Create a listen event callback with the specified filters.
190 /// The parameters localID,itemID are needed to uniquely identify
191 /// the script during 'peek' time. Parameter hostID is needed to
192 /// determine the position of the script.
193 /// </summary>
194 /// <param name="localID">localID of the script engine</param>
195 /// <param name="itemID">UUID of the script engine</param>
196 /// <param name="hostID">UUID of the SceneObjectPart</param>
197 /// <param name="channel">channel to listen on</param>
198 /// <param name="name">name to filter on</param>
199 /// <param name="id">
200 /// key to filter on (user given, could be totally faked)
201 /// </param>
202 /// <param name="msg">msg to filter on</param> 176 /// <param name="msg">msg to filter on</param>
203 /// <param name="regexBitfield">
204 /// Bitfield indicating which strings should be processed as regex.
205 /// </param>
206 /// <returns>number of the scripts handle</returns> 177 /// <returns>number of the scripts handle</returns>
207 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, 178 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
208 string name, UUID id, string msg, int regexBitfield)
209 { 179 {
210 return m_listenerManager.AddListener(localID, itemID, hostID, 180 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
211 channel, name, id, msg, regexBitfield);
212 } 181 }
213 182
214 /// <summary> 183 /// <summary>
@@ -357,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
357 if (channel == 0) 326 if (channel == 0)
358 { 327 {
359 // Channel 0 goes to viewer ONLY 328 // Channel 0 goes to viewer ONLY
360 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); 329 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target);
361 return true; 330 return true;
362 } 331 }
363 332
@@ -501,25 +470,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
501 m_curlisteners = 0; 470 m_curlisteners = 0;
502 } 471 }
503 472
504 public int AddListener(uint localID, UUID itemID, UUID hostID, 473 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
505 int channel, string name, UUID id, string msg)
506 {
507 return AddListener(localID, itemID, hostID, channel, name, id,
508 msg, 0);
509 }
510
511 public int AddListener(uint localID, UUID itemID, UUID hostID,
512 int channel, string name, UUID id, string msg,
513 int regexBitfield)
514 { 474 {
515 // do we already have a match on this particular filter event? 475 // do we already have a match on this particular filter event?
516 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, 476 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
517 msg);
518 477
519 if (coll.Count > 0) 478 if (coll.Count > 0)
520 { 479 {
521 // special case, called with same filter settings, return same 480 // special case, called with same filter settings, return same handle
522 // handle (2008-05-02, tested on 1.21.1 server, still holds) 481 // (2008-05-02, tested on 1.21.1 server, still holds)
523 return coll[0].GetHandle(); 482 return coll[0].GetHandle();
524 } 483 }
525 484
@@ -531,9 +490,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
531 490
532 if (newHandle > 0) 491 if (newHandle > 0)
533 { 492 {
534 ListenerInfo li = new ListenerInfo(newHandle, localID, 493 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg);
535 itemID, hostID, channel, name, id, msg,
536 regexBitfield);
537 494
538 List<ListenerInfo> listeners; 495 List<ListenerInfo> listeners;
539 if (!m_listeners.TryGetValue(channel,out listeners)) 496 if (!m_listeners.TryGetValue(channel,out listeners))
@@ -674,22 +631,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
674 return -1; 631 return -1;
675 } 632 }
676 633
677 /// These are duplicated from ScriptBaseClass
678 /// http://opensimulator.org/mantis/view.php?id=6106#c21945
679 #region Constants for the bitfield parameter of osListenRegex
680
681 /// <summary>
682 /// process name parameter as regex
683 /// </summary>
684 public const int OS_LISTEN_REGEX_NAME = 0x1;
685
686 /// <summary>
687 /// process message parameter as regex
688 /// </summary>
689 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
690
691 #endregion
692
693 // Theres probably a more clever and efficient way to 634 // Theres probably a more clever and efficient way to
694 // do this, maybe with regex. 635 // do this, maybe with regex.
695 // PM2008: Ha, one could even be smart and define a specialized Enumerator. 636 // PM2008: Ha, one could even be smart and define a specialized Enumerator.
@@ -715,10 +656,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
715 { 656 {
716 continue; 657 continue;
717 } 658 }
718 if (li.GetName().Length > 0 && ( 659 if (li.GetName().Length > 0 && !li.GetName().Equals(name))
719 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
720 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
721 ))
722 { 660 {
723 continue; 661 continue;
724 } 662 }
@@ -726,10 +664,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
726 { 664 {
727 continue; 665 continue;
728 } 666 }
729 if (li.GetMessage().Length > 0 && ( 667 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg))
730 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
731 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
732 ))
733 { 668 {
734 continue; 669 continue;
735 } 670 }
@@ -762,13 +697,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
762 { 697 {
763 int idx = 0; 698 int idx = 0;
764 Object[] item = new Object[6]; 699 Object[] item = new Object[6];
765 int dataItemLength = 6;
766 700
767 while (idx < data.Length) 701 while (idx < data.Length)
768 { 702 {
769 dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; 703 Array.Copy(data, idx, item, 0, 6);
770 item = new Object[dataItemLength];
771 Array.Copy(data, idx, item, 0, dataItemLength);
772 704
773 ListenerInfo info = 705 ListenerInfo info =
774 ListenerInfo.FromData(localID, itemID, hostID, item); 706 ListenerInfo.FromData(localID, itemID, hostID, item);
@@ -780,12 +712,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
780 m_listeners[(int)item[2]].Add(info); 712 m_listeners[(int)item[2]].Add(info);
781 } 713 }
782 714
783 idx+=dataItemLength; 715 idx+=6;
784 } 716 }
785 } 717 }
786 } 718 }
787 719
788 public class ListenerInfo : IWorldCommListenerInfo 720 public class ListenerInfo: IWorldCommListenerInfo
789 { 721 {
790 private bool m_active; // Listener is active or not 722 private bool m_active; // Listener is active or not
791 private int m_handle; // Assigned handle of this listener 723 private int m_handle; // Assigned handle of this listener
@@ -799,29 +731,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
799 731
800 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) 732 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
801 { 733 {
802 Initialise(handle, localID, ItemID, hostID, channel, name, id, 734 Initialise(handle, localID, ItemID, hostID, channel, name, id, message);
803 message, 0);
804 }
805
806 public ListenerInfo(int handle, uint localID, UUID ItemID,
807 UUID hostID, int channel, string name, UUID id,
808 string message, int regexBitfield)
809 {
810 Initialise(handle, localID, ItemID, hostID, channel, name, id,
811 message, regexBitfield);
812 } 735 }
813 736
814 public ListenerInfo(ListenerInfo li, string name, UUID id, string message) 737 public ListenerInfo(ListenerInfo li, string name, UUID id, string message)
815 { 738 {
816 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); 739 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message);
817 }
818
819 public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield)
820 {
821 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield);
822 } 740 }
823 741
824 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) 742 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name,
743 UUID id, string message)
825 { 744 {
826 m_active = true; 745 m_active = true;
827 m_handle = handle; 746 m_handle = handle;
@@ -832,12 +751,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
832 m_name = name; 751 m_name = name;
833 m_id = id; 752 m_id = id;
834 m_message = message; 753 m_message = message;
835 RegexBitfield = regexBitfield;
836 } 754 }
837 755
838 public Object[] GetSerializationData() 756 public Object[] GetSerializationData()
839 { 757 {
840 Object[] data = new Object[7]; 758 Object[] data = new Object[6];
841 759
842 data[0] = m_active; 760 data[0] = m_active;
843 data[1] = m_handle; 761 data[1] = m_handle;
@@ -845,19 +763,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
845 data[3] = m_name; 763 data[3] = m_name;
846 data[4] = m_id; 764 data[4] = m_id;
847 data[5] = m_message; 765 data[5] = m_message;
848 data[6] = RegexBitfield;
849 766
850 return data; 767 return data;
851 } 768 }
852 769
853 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) 770 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
854 { 771 {
855 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); 772 ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
856 linfo.m_active = (bool)data[0]; 773 ItemID, hostID, (int)data[2], (string)data[3],
857 if (data.Length >= 7) 774 (UUID)data[4], (string)data[5]);
858 { 775 linfo.m_active=(bool)data[0];
859 linfo.RegexBitfield = (int)data[6];
860 }
861 776
862 return linfo; 777 return linfo;
863 } 778 }
@@ -916,7 +831,5 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
916 { 831 {
917 return m_id; 832 return m_id;
918 } 833 }
919
920 public int RegexBitfield { get; private set; }
921 } 834 }
922} 835}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 1e1c7d0..008465f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -56,8 +56,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
56 56
57 private bool m_Enabled = false; 57 private bool m_Enabled = false;
58 58
59 private AssetPermissions m_AssetPerms;
60
61 public Type ReplaceableInterface 59 public Type ReplaceableInterface
62 { 60 {
63 get { return null; } 61 get { return null; }
@@ -130,9 +128,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
130 if (m_LocalAssetServiceURI != string.Empty) 128 if (m_LocalAssetServiceURI != string.Empty)
131 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); 129 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/');
132 130
133 IConfig hgConfig = source.Configs["HGAssetService"];
134 m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null
135
136 m_Enabled = true; 131 m_Enabled = true;
137 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); 132 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled");
138 } 133 }
@@ -211,11 +206,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
211 asset = m_HGService.Get(id); 206 asset = m_HGService.Get(id);
212 if (asset != null) 207 if (asset != null)
213 { 208 {
214 // Now store it locally, if allowed 209 // Now store it locally
215 if (m_AssetPerms.AllowedImport(asset.Type)) 210 // For now, let me just do it for textures and scripts
211 if (((AssetType)asset.Type == AssetType.Texture) ||
212 ((AssetType)asset.Type == AssetType.LSLBytecode) ||
213 ((AssetType)asset.Type == AssetType.LSLText))
214 {
216 m_GridService.Store(asset); 215 m_GridService.Store(asset);
217 else 216 }
218 return null;
219 } 217 }
220 } 218 }
221 else 219 else
@@ -330,12 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
330 328
331 string id = string.Empty; 329 string id = string.Empty;
332 if (IsHG(asset.ID)) 330 if (IsHG(asset.ID))
333 { 331 id = m_HGService.Store(asset);
334 if (m_AssetPerms.AllowedExport(asset.Type))
335 id = m_HGService.Store(asset);
336 else
337 return String.Empty;
338 }
339 else 332 else
340 id = m_GridService.Store(asset); 333 id = m_GridService.Store(asset);
341 334
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 449c1f1..c78915f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
204 public byte[] GetData(string id) 204 public byte[] GetData(string id)
205 { 205 {
206// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); 206// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
207 207
208 AssetBase asset = null; 208 AssetBase asset = m_Cache.Get(id);
209
210 if (m_Cache != null)
211 asset = m_Cache.Get(id);
212 209
213 if (asset != null) 210 if (asset != null)
214 return asset.Data; 211 return asset.Data;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
deleted file mode 100644
index 1982473..0000000
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Threading;
33using log4net.Config;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
40using OpenSim.Tests.Common;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{
44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase
46 {
47 [Test]
48 public void TestAddAsset()
49 {
50 TestHelpers.InMethod();
51// TestHelpers.EnableLogging();
52
53 IConfigSource config = new IniConfigSource();
54 config.AddConfig("Modules");
55 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
56 config.AddConfig("AssetService");
57 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
58 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
59
60 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
61 lasc.Initialise(config);
62
63 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
64 lasc.Store(a1);
65
66 AssetBase retreivedA1 = lasc.Get(a1.ID);
67 Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
68 Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
69 Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
70
71 AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
72 Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
73
74 byte[] retrievedA1Data = lasc.GetData(a1.ID);
75 Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
76
77 // TODO: Add cache and check that this does receive a copy of the asset
78 }
79
80 [Test]
81 public void TestAddTemporaryAsset()
82 {
83 TestHelpers.InMethod();
84// TestHelpers.EnableLogging();
85
86 IConfigSource config = new IniConfigSource();
87 config.AddConfig("Modules");
88 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
89 config.AddConfig("AssetService");
90 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
91 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
92
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config);
95
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true;
98
99 lasc.Store(a1);
100
101 Assert.That(lasc.Get(a1.ID), Is.Null);
102 Assert.That(lasc.GetData(a1.ID), Is.Null);
103 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
104
105 // TODO: Add cache and check that this does receive a copy of the asset
106 }
107
108 [Test]
109 public void TestAddLocalAsset()
110 {
111 TestHelpers.InMethod();
112// TestHelpers.EnableLogging();
113
114 IConfigSource config = new IniConfigSource();
115 config.AddConfig("Modules");
116 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
117 config.AddConfig("AssetService");
118 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
119 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
120
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config);
123
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true;
126
127 lasc.Store(a1);
128
129 Assert.That(lasc.Get(a1.ID), Is.Null);
130 Assert.That(lasc.GetData(a1.ID), Is.Null);
131 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
132
133 // TODO: Add cache and check that this does receive a copy of the asset
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 4338133..b286d17 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,15 +43,11 @@ using OpenSim.Tests.Common;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class GridConnectorsTests : OpenSimTestCase 46 public class GridConnectorsTests
47 { 47 {
48 LocalGridServicesConnector m_LocalConnector; 48 LocalGridServicesConnector m_LocalConnector;
49 49 private void SetUp()
50 [SetUp]
51 public override void SetUp()
52 { 50 {
53 base.SetUp();
54
55 IConfigSource config = new IniConfigSource(); 51 IConfigSource config = new IniConfigSource();
56 config.AddConfig("Modules"); 52 config.AddConfig("Modules");
57 config.AddConfig("GridService"); 53 config.AddConfig("GridService");
@@ -75,6 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
75 TestHelpers.InMethod(); 71 TestHelpers.InMethod();
76// log4net.Config.XmlConfigurator.Configure(); 72// log4net.Config.XmlConfigurator.Configure();
77 73
74 SetUp();
75
78 // Create 4 regions 76 // Create 4 regions
79 GridRegion r1 = new GridRegion(); 77 GridRegion r1 = new GridRegion();
80 r1.RegionName = "Test Region 1"; 78 r1.RegionName = "Test Region 1";
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 221f815..b0edce7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -65,13 +65,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
65 65
66 public void OnMakeRootAgent(ScenePresence sp) 66 public void OnMakeRootAgent(ScenePresence sp)
67 { 67 {
68// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
69
68 if (sp.PresenceType != PresenceType.Npc) 70 if (sp.PresenceType != PresenceType.Npc)
69 {
70 string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID);
71 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName);
72 m_GridUserService.SetLastPosition( 71 m_GridUserService.SetLastPosition(
73 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 72 sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
74 }
75 } 73 }
76 74
77 public void OnNewClient(IClientAPI client) 75 public void OnNewClient(IClientAPI client)
@@ -84,16 +82,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
84 if (client.SceneAgent.IsChildAgent) 82 if (client.SceneAgent.IsChildAgent)
85 return; 83 return;
86 84
87 string userId = client.AgentId.ToString(); 85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
88 if (client.Scene is Scene)
89 {
90 Scene s = (Scene)client.Scene;
91 userId = s.UserManagementModule.GetUserUUI(client.AgentId);
92 }
93 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName);
94
95 m_GridUserService.LoggedOut( 86 m_GridUserService.LoggedOut(
96 userId, client.SessionId, client.Scene.RegionInfo.RegionID, 87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
97 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); 88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
98 } 89 }
99 } 90 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index 04acf67..badb552 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -44,9 +44,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int KEEPTIME = 30; // 30 secs
48 private ExpiringCache<string, GridUserInfo> m_Infos = new ExpiringCache<string, GridUserInfo>();
49
50 #region ISharedRegionModule 47 #region ISharedRegionModule
51 48
52 private bool m_Enabled = false; 49 private bool m_Enabled = false;
@@ -131,60 +128,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
131 128
132 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) 129 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
133 { 130 {
134 if (m_Infos.Contains(userID))
135 m_Infos.Remove(userID);
136
137 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); 131 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat);
138 } 132 }
139 133
140 134
141 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 135 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
142 { 136 {
143 if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) 137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt);
144 {
145 // Update the cache too
146 GridUserInfo info = null;
147 if (m_Infos.TryGetValue(userID, out info))
148 {
149 info.HomeRegionID = regionID;
150 info.HomePosition = position;
151 info.HomeLookAt = lookAt;
152 }
153 return true;
154 }
155
156 return false;
157 } 138 }
158 139
159 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) 140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
160 { 141 {
161 if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) 142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt);
162 {
163 // Update the cache too
164 GridUserInfo info = null;
165 if (m_Infos.TryGetValue(userID, out info))
166 {
167 info.LastRegionID = regionID;
168 info.LastPosition = position;
169 info.LastLookAt = lookAt;
170 }
171 return true;
172 }
173
174 return false;
175 } 143 }
176 144
177 public GridUserInfo GetGridUserInfo(string userID) 145 public GridUserInfo GetGridUserInfo(string userID)
178 { 146 {
179 GridUserInfo info = null; 147 return m_RemoteConnector.GetGridUserInfo(userID);
180 if (m_Infos.TryGetValue(userID, out info))
181 return info;
182
183 info = m_RemoteConnector.GetGridUserInfo(userID);
184
185 m_Infos.AddOrUpdate(userID, info, KEEPTIME);
186
187 return info;
188 } 148 }
189 149
190 public GridUserInfo[] GetGridUserInfo(string[] userID) 150 public GridUserInfo[] GetGridUserInfo(string[] userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 8ed1833..6eb99ea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -313,11 +313,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
313 313
314 if (m_scenes.ContainsKey(destination.RegionID)) 314 if (m_scenes.ContainsKey(destination.RegionID))
315 { 315 {
316// m_log.DebugFormat( 316 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); });
317// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
318// s.RegionInfo.RegionName, destination.RegionHandle);
319
320 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
321 return true; 317 return true;
322 } 318 }
323 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index ade5e76..619550c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization; 44using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
46using System.Threading;
47 46
48namespace OpenSim.Region.CoreModules.World.Archiver 47namespace OpenSim.Region.CoreModules.World.Archiver
49{ 48{
@@ -53,30 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
53 public class ArchiveReadRequest 52 public class ArchiveReadRequest
54 { 53 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// Contains data used while dearchiving a single scene.
59 /// </summary>
60 private class DearchiveContext
61 {
62 public Scene Scene { get; set; }
63
64 public List<string> SerialisedSceneObjects { get; set; }
65
66 public List<string> SerialisedParcels { get; set; }
67
68 public List<SceneObjectGroup> SceneObjects { get; set; }
69
70 public DearchiveContext(Scene scene)
71 {
72 Scene = scene;
73 SerialisedSceneObjects = new List<string>();
74 SerialisedParcels = new List<string>();
75 SceneObjects = new List<SceneObjectGroup>();
76 }
77 }
78 55
79
80 /// <summary> 56 /// <summary>
81 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 57 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
82 /// bumps here should be compatible. 58 /// bumps here should be compatible.
@@ -86,10 +62,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
86 /// <summary> 62 /// <summary>
87 /// Has the control file been loaded for this archive? 63 /// Has the control file been loaded for this archive?
88 /// </summary> 64 /// </summary>
89 public bool ControlFileLoaded { get; private set; } 65 public bool ControlFileLoaded { get; private set; }
90 66
91 protected string m_loadPath; 67 protected Scene m_scene;
92 protected Scene m_rootScene;
93 protected Stream m_loadStream; 68 protected Stream m_loadStream;
94 protected Guid m_requestId; 69 protected Guid m_requestId;
95 protected string m_errorMessage; 70 protected string m_errorMessage;
@@ -116,27 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
116 { 91 {
117 if (m_UserMan == null) 92 if (m_UserMan == null)
118 { 93 {
119 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>(); 94 m_UserMan = m_scene.RequestModuleInterface<IUserManagement>();
120 } 95 }
121 return m_UserMan; 96 return m_UserMan;
122 } 97 }
123 } 98 }
124 99
125 /// <summary>
126 /// Used to cache lookups for valid groups.
127 /// </summary>
128 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
129
130 private IGroupsModule m_groupsModule;
131
132 private IAssetService m_assetService = null;
133
134
135 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) 100 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
136 { 101 {
137 m_rootScene = scene; 102 m_scene = scene;
138 103
139 m_loadPath = loadPath;
140 try 104 try
141 { 105 {
142 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); 106 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
@@ -156,15 +120,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
156 120
157 // Zero can never be a valid user id 121 // Zero can never be a valid user id
158 m_validUserUuids[UUID.Zero] = false; 122 m_validUserUuids[UUID.Zero] = false;
159
160 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
161 m_assetService = m_rootScene.AssetService;
162 } 123 }
163 124
164 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 125 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
165 { 126 {
166 m_rootScene = scene; 127 m_scene = scene;
167 m_loadPath = null;
168 m_loadStream = loadStream; 128 m_loadStream = loadStream;
169 m_merge = merge; 129 m_merge = merge;
170 m_skipAssets = skipAssets; 130 m_skipAssets = skipAssets;
@@ -172,9 +132,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 132
173 // Zero can never be a valid user id 133 // Zero can never be a valid user id
174 m_validUserUuids[UUID.Zero] = false; 134 m_validUserUuids[UUID.Zero] = false;
175
176 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
177 m_assetService = m_rootScene.AssetService;
178 } 135 }
179 136
180 /// <summary> 137 /// <summary>
@@ -182,25 +139,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
182 /// </summary> 139 /// </summary>
183 public void DearchiveRegion() 140 public void DearchiveRegion()
184 { 141 {
142 // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
143 DearchiveRegion0DotStar();
144 }
145
146 private void DearchiveRegion0DotStar()
147 {
185 int successfulAssetRestores = 0; 148 int successfulAssetRestores = 0;
186 int failedAssetRestores = 0; 149 int failedAssetRestores = 0;
150 List<string> serialisedSceneObjects = new List<string>();
151 List<string> serialisedParcels = new List<string>();
152 string filePath = "NONE";
187 153
188 DearchiveScenesInfo dearchivedScenes; 154 TarArchiveReader archive = new TarArchiveReader(m_loadStream);
189
190 // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
191 // Therefore, we have to keep track of the dearchive context of all the scenes.
192 Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
193
194 string fullPath = "NONE";
195 TarArchiveReader archive = null;
196 byte[] data; 155 byte[] data;
197 TarArchiveReader.TarEntryType entryType; 156 TarArchiveReader.TarEntryType entryType;
198 157
199 try 158 try
200 { 159 {
201 FindAndLoadControlFile(out archive, out dearchivedScenes); 160 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
202
203 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
204 { 161 {
205 //m_log.DebugFormat( 162 //m_log.DebugFormat(
206 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 163 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
@@ -208,30 +165,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
208 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 165 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
209 continue; 166 continue;
210 167
211
212 // Find the scene that this file belongs to
213
214 Scene scene;
215 string filePath;
216 if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
217 continue; // this file belongs to a region that we're not loading
218
219 DearchiveContext sceneContext = null;
220 if (scene != null)
221 {
222 if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
223 {
224 sceneContext = new DearchiveContext(scene);
225 sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
226 }
227 }
228
229
230 // Process the file
231
232 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) 168 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
233 { 169 {
234 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); 170 serialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
235 } 171 }
236 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) 172 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
237 { 173 {
@@ -245,19 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
245 } 181 }
246 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) 182 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
247 { 183 {
248 LoadTerrain(scene, filePath, data); 184 LoadTerrain(filePath, data);
249 } 185 }
250 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 186 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
251 { 187 {
252 LoadRegionSettings(scene, filePath, data, dearchivedScenes); 188 LoadRegionSettings(filePath, data);
253 } 189 }
254 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) 190 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
255 { 191 {
256 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); 192 serialisedParcels.Add(Encoding.UTF8.GetString(data));
257 } 193 }
258 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 194 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
259 { 195 {
260 // Ignore, because we already read the control file 196 LoadControlFile(filePath, data);
261 } 197 }
262 } 198 }
263 199
@@ -265,16 +201,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
265 } 201 }
266 catch (Exception e) 202 catch (Exception e)
267 { 203 {
268 m_log.Error( 204 m_log.ErrorFormat(
269 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); 205 "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e);
270 m_errorMessage += e.ToString(); 206 m_errorMessage += e.ToString();
271 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage); 207 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
272 return; 208 return;
273 } 209 }
274 finally 210 finally
275 { 211 {
276 if (archive != null) 212 archive.Close();
277 archive.Close();
278 } 213 }
279 214
280 if (!m_skipAssets) 215 if (!m_skipAssets)
@@ -288,143 +223,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 } 223 }
289 } 224 }
290 225
291 foreach (DearchiveContext sceneContext in sceneContexts.Values) 226 if (!m_merge)
292 { 227 {
293 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); 228 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
294 229 m_scene.DeleteAllSceneObjects();
295 if (!m_merge)
296 {
297 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
298 sceneContext.Scene.DeleteAllSceneObjects();
299 }
300
301 try
302 {
303 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
304 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
305
306 // Inform any interested parties that the region has changed. We waited until now so that all
307 // of the region's objects will be loaded when we send this notification.
308 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
309 if (estateModule != null)
310 estateModule.TriggerRegionInfoChange();
311 }
312 catch (Exception e)
313 {
314 m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
315 m_errorMessage += e.ToString();
316 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
317 return;
318 }
319 } 230 }
320 231
321 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so 232 LoadParcels(serialisedParcels);
322 // that users can enter the scene. If we allow the scripts to start in the loop above 233 LoadObjects(serialisedSceneObjects);
323 // then they significantly increase the time until the OAR finishes loading.
324 Util.FireAndForget(delegate(object o)
325 {
326 Thread.Sleep(15000);
327 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
328
329 foreach (DearchiveContext sceneContext in sceneContexts.Values)
330 {
331 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
332 {
333 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
334 sceneObject.ResumeScripts();
335 }
336
337 sceneContext.SceneObjects.Clear();
338 }
339 });
340 234
341 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 235 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
342 236
343 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); 237 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
344 }
345
346 /// <summary>
347 /// Searches through the files in the archive for the control file, and reads it.
348 /// We must read the control file first, in order to know which regions are available.
349 /// </summary>
350 /// <remarks>
351 /// In most cases the control file *is* first, since that's how we create archives. However,
352 /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
353 /// </remarks>
354 /// <param name="archive"></param>
355 /// <param name="dearchivedScenes"></param>
356 private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
357 {
358 archive = new TarArchiveReader(m_loadStream);
359 dearchivedScenes = new DearchiveScenesInfo();
360
361 string filePath;
362 byte[] data;
363 TarArchiveReader.TarEntryType entryType;
364 bool firstFile = true;
365
366 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
367 {
368 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
369 continue;
370
371 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
372 {
373 LoadControlFile(filePath, data, dearchivedScenes);
374
375 // Find which scenes are available in the simulator
376 ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
377 SceneManager.Instance.ForEachScene(delegate(Scene scene2)
378 {
379 simulatorScenes.AddScene(scene2);
380 });
381 simulatorScenes.CalcSceneLocations();
382 dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
383
384 // If the control file wasn't the first file then reset the read pointer
385 if (!firstFile)
386 {
387 m_log.Warn("Control file wasn't the first file in the archive");
388 if (m_loadStream.CanSeek)
389 {
390 m_loadStream.Seek(0, SeekOrigin.Begin);
391 }
392 else if (m_loadPath != null)
393 {
394 archive.Close();
395 archive = null;
396 m_loadStream.Close();
397 m_loadStream = null;
398 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
399 archive = new TarArchiveReader(m_loadStream);
400 }
401 else
402 {
403 // There isn't currently a scenario where this happens, but it's best to add a check just in case
404 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
405 }
406 }
407
408 return;
409 }
410
411 firstFile = false;
412 }
413
414 throw new Exception("Control file not found");
415 } 238 }
416 239
417 /// <summary> 240 /// <summary>
418 /// Load serialized scene objects. 241 /// Load serialized scene objects.
419 /// </summary> 242 /// </summary>
420 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects) 243 /// <param name="serialisedSceneObjects"></param>
244 protected void LoadObjects(List<string> serialisedSceneObjects)
421 { 245 {
422 // Reload serialized prims 246 // Reload serialized prims
423 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 247 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
424 248
425 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; 249 UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject;
426 250
427 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); 251 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
428 int sceneObjectsLoadedCount = 0; 252 int sceneObjectsLoadedCount = 0;
429 253
430 foreach (string serialisedSceneObject in serialisedSceneObjects) 254 foreach (string serialisedSceneObject in serialisedSceneObjects)
@@ -445,7 +269,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
445 269
446 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 270 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
447 271
448 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 272 bool isTelehub = (sceneObject.UUID == oldTelehubUUID);
449 273
450 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 274 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
451 // on the same region server and multiple examples a single object archive to be imported 275 // on the same region server and multiple examples a single object archive to be imported
@@ -455,8 +279,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
455 if (isTelehub) 279 if (isTelehub)
456 { 280 {
457 // Change the Telehub Object to the new UUID 281 // Change the Telehub Object to the new UUID
458 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; 282 m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
459 scene.RegionInfo.RegionSettings.Save(); 283 m_scene.RegionInfo.RegionSettings.Save();
460 oldTelehubUUID = UUID.Zero; 284 oldTelehubUUID = UUID.Zero;
461 } 285 }
462 286
@@ -466,20 +290,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
466 { 290 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty) 291 if (part.CreatorData == null || part.CreatorData == string.Empty)
468 { 292 {
469 if (!ResolveUserUuid(scene, part.CreatorID)) 293 if (!ResolveUserUuid(part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 294 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
471 } 295 }
472 if (UserManager != null) 296 if (UserManager != null)
473 UserManager.AddUser(part.CreatorID, part.CreatorData); 297 UserManager.AddUser(part.CreatorID, part.CreatorData);
474 298
475 if (!ResolveUserUuid(scene, part.OwnerID)) 299 if (!ResolveUserUuid(part.OwnerID))
476 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 300 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
477
478 if (!ResolveUserUuid(scene, part.LastOwnerID))
479 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
480 301
481 if (!ResolveGroupUuid(part.GroupID)) 302 if (!ResolveUserUuid(part.LastOwnerID))
482 part.GroupID = UUID.Zero; 303 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
483 304
484 // And zap any troublesome sit target information 305 // And zap any troublesome sit target information
485// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 306// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -490,14 +311,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
490 // being no copy/no mod for everyone 311 // being no copy/no mod for everyone
491 lock (part.TaskInventory) 312 lock (part.TaskInventory)
492 { 313 {
493 if (!ResolveUserUuid(scene, part.CreatorID)) 314 if (!ResolveUserUuid(part.CreatorID))
494 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 315 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
495 316
496 if (!ResolveUserUuid(scene, part.OwnerID)) 317 if (!ResolveUserUuid(part.OwnerID))
497 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 318 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
498 319
499 if (!ResolveUserUuid(scene, part.LastOwnerID)) 320 if (!ResolveUserUuid(part.LastOwnerID))
500 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 321 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
501 322
502 // And zap any troublesome sit target information 323 // And zap any troublesome sit target information
503 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 324 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -510,31 +331,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
510 TaskInventoryDictionary inv = part.TaskInventory; 331 TaskInventoryDictionary inv = part.TaskInventory;
511 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 332 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
512 { 333 {
513 if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) 334 if (!ResolveUserUuid(kvp.Value.OwnerID))
514 { 335 {
515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 336 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
516 } 337 }
517
518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 338 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
519 { 339 {
520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) 340 if (!ResolveUserUuid(kvp.Value.CreatorID))
521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 341 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
522 } 342 }
523
524 if (UserManager != null) 343 if (UserManager != null)
525 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 344 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
526
527 if (!ResolveGroupUuid(kvp.Value.GroupID))
528 kvp.Value.GroupID = UUID.Zero;
529 } 345 }
530 part.TaskInventory.LockItemsForRead(false); 346 part.TaskInventory.LockItemsForRead(false);
531 } 347 }
532 } 348 }
533 349
534 if (scene.AddRestoredSceneObject(sceneObject, true, false)) 350 if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
535 { 351 {
536 sceneObjectsLoadedCount++; 352 sceneObjectsLoadedCount++;
537 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); 353 sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
538 sceneObject.ResumeScripts(); 354 sceneObject.ResumeScripts();
539 } 355 }
540 } 356 }
@@ -549,17 +365,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
549 if (oldTelehubUUID != UUID.Zero) 365 if (oldTelehubUUID != UUID.Zero)
550 { 366 {
551 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 367 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
552 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 368 m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
553 scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 369 m_scene.RegionInfo.RegionSettings.ClearSpawnPoints();
554 } 370 }
555 } 371 }
556 372
557 /// <summary> 373 /// <summary>
558 /// Load serialized parcels. 374 /// Load serialized parcels.
559 /// </summary> 375 /// </summary>
560 /// <param name="scene"></param>
561 /// <param name="serialisedParcels"></param> 376 /// <param name="serialisedParcels"></param>
562 protected void LoadParcels(Scene scene, List<string> serialisedParcels) 377 protected void LoadParcels(List<string> serialisedParcels)
563 { 378 {
564 // Reload serialized parcels 379 // Reload serialized parcels
565 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 380 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
@@ -567,27 +382,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
567 foreach (string serialisedParcel in serialisedParcels) 382 foreach (string serialisedParcel in serialisedParcels)
568 { 383 {
569 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 384 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
385 if (!ResolveUserUuid(parcel.OwnerID))
386 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
570 387
571 // Validate User and Group UUID's
572
573 if (!ResolveUserUuid(scene, parcel.OwnerID))
574 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
575
576 if (!ResolveGroupUuid(parcel.GroupID))
577 {
578 parcel.GroupID = UUID.Zero;
579 parcel.IsGroupOwned = false;
580 }
581
582 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
583 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
584 {
585 if (ResolveUserUuid(scene, entry.AgentID))
586 accessList.Add(entry);
587 // else, drop this access rule
588 }
589 parcel.ParcelAccessList = accessList;
590
591// m_log.DebugFormat( 388// m_log.DebugFormat(
592// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 389// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
593// parcel.Name, parcel.LocalID, parcel.Area); 390// parcel.Name, parcel.LocalID, parcel.Area);
@@ -598,24 +395,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
598 if (!m_merge) 395 if (!m_merge)
599 { 396 {
600 bool setupDefaultParcel = (landData.Count == 0); 397 bool setupDefaultParcel = (landData.Count == 0);
601 scene.LandChannel.Clear(setupDefaultParcel); 398 m_scene.LandChannel.Clear(setupDefaultParcel);
602 } 399 }
603 400
604 scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 401 m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
605 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 402 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
606 } 403 }
607 404
608 /// <summary> 405 /// <summary>
609 /// Look up the given user id to check whether it's one that is valid for this grid. 406 /// Look up the given user id to check whether it's one that is valid for this grid.
610 /// </summary> 407 /// </summary>
611 /// <param name="scene"></param>
612 /// <param name="uuid"></param> 408 /// <param name="uuid"></param>
613 /// <returns></returns> 409 /// <returns></returns>
614 private bool ResolveUserUuid(Scene scene, UUID uuid) 410 private bool ResolveUserUuid(UUID uuid)
615 { 411 {
616 if (!m_validUserUuids.ContainsKey(uuid)) 412 if (!m_validUserUuids.ContainsKey(uuid))
617 { 413 {
618 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); 414 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
619 m_validUserUuids.Add(uuid, account != null); 415 m_validUserUuids.Add(uuid, account != null);
620 } 416 }
621 417
@@ -623,30 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
623 } 419 }
624 420
625 /// <summary> 421 /// <summary>
626 /// Look up the given group id to check whether it's one that is valid for this grid.
627 /// </summary>
628 /// <param name="uuid"></param>
629 /// <returns></returns>
630 private bool ResolveGroupUuid(UUID uuid)
631 {
632 if (uuid == UUID.Zero)
633 return true; // this means the object has no group
634
635 if (!m_validGroupUuids.ContainsKey(uuid))
636 {
637 bool exists;
638
639 if (m_groupsModule == null)
640 exists = false;
641 else
642 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
643
644 m_validGroupUuids.Add(uuid, exists);
645 }
646
647 return m_validGroupUuids[uuid];
648 }
649
650 /// Load an asset 422 /// Load an asset
651 /// </summary> 423 /// </summary>
652 /// <param name="assetFilename"></param> 424 /// <param name="assetFilename"></param>
@@ -670,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
670 string extension = filename.Substring(i); 442 string extension = filename.Substring(i);
671 string uuid = filename.Remove(filename.Length - extension.Length); 443 string uuid = filename.Remove(filename.Length - extension.Length);
672 444
673 if (m_assetService.GetMetadata(uuid) != null) 445 if (m_scene.AssetService.GetMetadata(uuid) != null)
674 { 446 {
675 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 447 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
676 return true; 448 return true;
@@ -690,7 +462,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
690 462
691 // We're relying on the asset service to do the sensible thing and not store the asset if it already 463 // We're relying on the asset service to do the sensible thing and not store the asset if it already
692 // exists. 464 // exists.
693 m_assetService.Store(asset); 465 m_scene.AssetService.Store(asset);
694 466
695 /** 467 /**
696 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so 468 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
@@ -718,14 +490,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
718 /// <summary> 490 /// <summary>
719 /// Load region settings data 491 /// Load region settings data
720 /// </summary> 492 /// </summary>
721 /// <param name="scene"></param>
722 /// <param name="settingsPath"></param> 493 /// <param name="settingsPath"></param>
723 /// <param name="data"></param> 494 /// <param name="data"></param>
724 /// <param name="dearchivedScenes"></param>
725 /// <returns> 495 /// <returns>
726 /// true if settings were loaded successfully, false otherwise 496 /// true if settings were loaded successfully, false otherwise
727 /// </returns> 497 /// </returns>
728 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) 498 private bool LoadRegionSettings(string settingsPath, byte[] data)
729 { 499 {
730 RegionSettings loadedRegionSettings; 500 RegionSettings loadedRegionSettings;
731 501
@@ -741,7 +511,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
741 return false; 511 return false;
742 } 512 }
743 513
744 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; 514 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
745 515
746 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; 516 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
747 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; 517 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
@@ -778,14 +548,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
778 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) 548 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
779 currentRegionSettings.AddSpawnPoint(sp); 549 currentRegionSettings.AddSpawnPoint(sp);
780 550
781 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
782 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
783
784 currentRegionSettings.Save(); 551 currentRegionSettings.Save();
785 552
786 scene.TriggerEstateSunUpdate(); 553 m_scene.TriggerEstateSunUpdate();
787 554
788 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>(); 555 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
556
789 if (estateModule != null) 557 if (estateModule != null)
790 estateModule.sendRegionHandshakeToAll(); 558 estateModule.sendRegionHandshakeToAll();
791 559
@@ -795,15 +563,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
795 /// <summary> 563 /// <summary>
796 /// Load terrain data 564 /// Load terrain data
797 /// </summary> 565 /// </summary>
798 /// <param name="scene"></param>
799 /// <param name="terrainPath"></param> 566 /// <param name="terrainPath"></param>
800 /// <param name="data"></param> 567 /// <param name="data"></param>
801 /// <returns> 568 /// <returns>
802 /// true if terrain was resolved successfully, false otherwise. 569 /// true if terrain was resolved successfully, false otherwise.
803 /// </returns> 570 /// </returns>
804 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 571 private bool LoadTerrain(string terrainPath, byte[] data)
805 { 572 {
806 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 573 ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>();
807 574
808 MemoryStream ms = new MemoryStream(data); 575 MemoryStream ms = new MemoryStream(data);
809 terrainModule.LoadFromStream(terrainPath, ms); 576 terrainModule.LoadFromStream(terrainPath, ms);
@@ -819,18 +586,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
819 /// </summary> 586 /// </summary>
820 /// <param name="path"></param> 587 /// <param name="path"></param>
821 /// <param name="data"></param> 588 /// <param name="data"></param>
822 /// <param name="dearchivedScenes"></param> 589 public void LoadControlFile(string path, byte[] data)
823 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
824 { 590 {
825 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 591 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
826 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 592 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
827 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 593 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
828 594
829 // Loaded metadata will be empty if no information exists in the archive 595 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
830 dearchivedScenes.LoadedCreationDateTime = 0;
831 dearchivedScenes.DefaultOriginalID = "";
832 596
833 bool multiRegion = false; 597 // Loaded metadata will empty if no information exists in the archive
598 currentRegionSettings.LoadedCreationDateTime = 0;
599 currentRegionSettings.LoadedCreationID = "";
834 600
835 while (xtr.Read()) 601 while (xtr.Read())
836 { 602 {
@@ -856,44 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
856 { 622 {
857 int value; 623 int value;
858 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 624 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
859 dearchivedScenes.LoadedCreationDateTime = value; 625 currentRegionSettings.LoadedCreationDateTime = value;
860 } 626 }
861 else if (xtr.Name.ToString() == "row") 627 else if (xtr.Name.ToString() == "id")
862 {
863 multiRegion = true;
864 dearchivedScenes.StartRow();
865 }
866 else if (xtr.Name.ToString() == "region")
867 {
868 dearchivedScenes.StartRegion();
869 }
870 else if (xtr.Name.ToString() == "id")
871 {
872 string id = xtr.ReadElementContentAsString();
873 dearchivedScenes.DefaultOriginalID = id;
874 if (multiRegion)
875 dearchivedScenes.SetRegionOriginalID(id);
876 }
877 else if (xtr.Name.ToString() == "dir")
878 { 628 {
879 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); 629 currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString();
880 } 630 }
881 } 631 }
882 } 632 }
883 633
884 dearchivedScenes.MultiRegionFormat = multiRegion; 634 currentRegionSettings.Save();
885 if (!multiRegion) 635
886 {
887 // Add the single scene
888 dearchivedScenes.StartRow();
889 dearchivedScenes.StartRegion();
890 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
891 dearchivedScenes.SetRegionDirectory("");
892 }
893
894 ControlFileLoaded = true; 636 ControlFileLoaded = true;
895
896 return dearchivedScenes;
897 } 637 }
898 } 638 }
899} 639} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
deleted file mode 100644
index d8dace2..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
+++ /dev/null
@@ -1,176 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35
36namespace OpenSim.Region.CoreModules.World.Archiver
37{
38 /// <summary>
39 /// A group of regions arranged in a rectangle, possibly with holes.
40 /// </summary>
41 /// <remarks>
42 /// The regions usually (but not necessarily) belong to an archive file, in which case we
43 /// store additional information used to create the archive (e.g., each region's
44 /// directory within the archive).
45 /// </remarks>
46 public class ArchiveScenesGroup
47 {
48 /// <summary>
49 /// All the regions. The outer dictionary contains rows (key: Y coordinate).
50 /// The inner dictionaries contain each row's regions (key: X coordinate).
51 /// </summary>
52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
53
54 /// <summary>
55 /// The subdirectory where each region is stored in the archive.
56 /// </summary>
57 protected Dictionary<UUID, string> m_regionDirs;
58
59 /// <summary>
60 /// The grid coordinates of the regions' bounding box.
61 /// </summary>
62 public Rectangle Rect { get; set; }
63
64
65 public ArchiveScenesGroup()
66 {
67 Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>();
68 m_regionDirs = new Dictionary<UUID, string>();
69 Rect = new Rectangle(0, 0, 0, 0);
70 }
71
72 public void AddScene(Scene scene)
73 {
74 uint x = scene.RegionInfo.RegionLocX;
75 uint y = scene.RegionInfo.RegionLocY;
76
77 SortedDictionary<uint, Scene> row;
78 if (!Regions.TryGetValue(y, out row))
79 {
80 row = new SortedDictionary<uint, Scene>();
81 Regions[y] = row;
82 }
83
84 row[x] = scene;
85 }
86
87 /// <summary>
88 /// Called after all the scenes have been added. Performs calculations that require
89 /// knowledge of all the scenes.
90 /// </summary>
91 public void CalcSceneLocations()
92 {
93 if (Regions.Count == 0)
94 return;
95
96 // Find the bounding rectangle
97
98 uint firstY = Regions.First().Key;
99 uint lastY = Regions.Last().Key;
100
101 uint? firstX = null;
102 uint? lastX = null;
103
104 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
105 {
106 uint curFirstX = row.First().Key;
107 uint curLastX = row.Last().Key;
108
109 firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX;
110 lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX;
111 }
112
113 Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1));
114
115
116 // Calculate the subdirectory in which each region will be stored in the archive
117
118 m_regionDirs.Clear();
119 ForEachScene(delegate(Scene scene)
120 {
121 // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name
122 string path = string.Format("{0}_{1}_{2}",
123 scene.RegionInfo.RegionLocX - Rect.X + 1,
124 scene.RegionInfo.RegionLocY - Rect.Y + 1,
125 scene.RegionInfo.RegionName.Replace(' ', '_'));
126 m_regionDirs[scene.RegionInfo.RegionID] = path;
127 });
128 }
129
130 /// <summary>
131 /// Returns the subdirectory where the region is stored.
132 /// </summary>
133 /// <param name="regionID"></param>
134 /// <returns></returns>
135 public string GetRegionDir(UUID regionID)
136 {
137 return m_regionDirs[regionID];
138 }
139
140 /// <summary>
141 /// Performs an action on all the scenes in this order: rows from South to North,
142 /// and within each row West to East.
143 /// </summary>
144 /// <param name="action"></param>
145 public void ForEachScene(Action<Scene> action)
146 {
147 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
148 {
149 foreach (Scene scene in row.Values)
150 {
151 action(scene);
152 }
153 }
154 }
155
156 /// <summary>
157 /// Returns the scene at position 'location'.
158 /// </summary>
159 /// <param name="location">A location in the grid</param>
160 /// <param name="scene">The scene at this location</param>
161 /// <returns>Whether the scene was found</returns>
162 public bool TryGetScene(Point location, out Scene scene)
163 {
164 SortedDictionary<uint, Scene> row;
165 if (Regions.TryGetValue((uint)location.Y, out row))
166 {
167 if (row.TryGetValue((uint)location.X, out scene))
168 return true;
169 }
170
171 scene = null;
172 return false;
173 }
174
175 }
176}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
deleted file mode 100644
index d751b1c..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ /dev/null
@@ -1,634 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46using OpenSim.Framework.Serialization.External;
47
48namespace OpenSim.Region.CoreModules.World.Archiver
49{
50 /// <summary>
51 /// Prepare to write out an archive.
52 /// </summary>
53 public class ArchiveWriteRequest
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// The minimum major version of OAR that we can write.
59 /// </summary>
60 public static int MIN_MAJOR_VERSION = 0;
61
62 /// <summary>
63 /// The maximum major version of OAR that we can write.
64 /// </summary>
65 public static int MAX_MAJOR_VERSION = 1;
66
67 /// <summary>
68 /// Whether we're saving a multi-region archive.
69 /// </summary>
70 public bool MultiRegionFormat { get; set; }
71
72 /// <summary>
73 /// Determine whether this archive will save assets. Default is true.
74 /// </summary>
75 public bool SaveAssets { get; set; }
76
77 /// <summary>
78 /// Determines which objects will be included in the archive, according to their permissions.
79 /// Default is null, meaning no permission checks.
80 /// </summary>
81 public string CheckPermissions { get; set; }
82
83 protected Scene m_rootScene;
84 protected Stream m_saveStream;
85 protected TarArchiveWriter m_archiveWriter;
86 protected Guid m_requestId;
87 protected Dictionary<string, object> m_options;
88
89 /// <summary>
90 /// Constructor
91 /// </summary>
92 /// <param name="module">Calling module</param>
93 /// <param name="savePath">The path to which to save data.</param>
94 /// <param name="requestId">The id associated with this request</param>
95 /// <exception cref="System.IO.IOException">
96 /// If there was a problem opening a stream for the file specified by the savePath
97 /// </exception>
98 public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId)
99 {
100 try
101 {
102 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
103 }
104 catch (EntryPointNotFoundException e)
105 {
106 m_log.ErrorFormat(
107 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
108 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
109 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
110 }
111 }
112
113 /// <summary>
114 /// Constructor.
115 /// </summary>
116 /// <param name="scene">The root scene to archive</param>
117 /// <param name="saveStream">The stream to which to save data.</param>
118 /// <param name="requestId">The id associated with this request</param>
119 public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId)
120 {
121 m_saveStream = saveStream;
122 }
123
124 protected ArchiveWriteRequest(Scene scene, Guid requestId)
125 {
126 m_rootScene = scene;
127 m_requestId = requestId;
128 m_archiveWriter = null;
129
130 MultiRegionFormat = false;
131 SaveAssets = true;
132 CheckPermissions = null;
133 }
134
135 /// <summary>
136 /// Archive the region requested.
137 /// </summary>
138 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
139 public void ArchiveRegion(Dictionary<string, object> options)
140 {
141 m_options = options;
142
143 if (options.ContainsKey("all") && (bool)options["all"])
144 MultiRegionFormat = true;
145
146 if (options.ContainsKey("noassets") && (bool)options["noassets"])
147 SaveAssets = false;
148
149 Object temp;
150 if (options.TryGetValue("checkPermissions", out temp))
151 CheckPermissions = (string)temp;
152
153
154 // Find the regions to archive
155 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
156 if (MultiRegionFormat)
157 {
158 m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count);
159 SceneManager.Instance.ForEachScene(delegate(Scene scene)
160 {
161 scenesGroup.AddScene(scene);
162 });
163 }
164 else
165 {
166 scenesGroup.AddScene(m_rootScene);
167 }
168 scenesGroup.CalcSceneLocations();
169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172
173 try
174 {
175 // Write out control file. It should be first so that it will be found ASAP when loading the file.
176 m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup));
177 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
178
179 // Archive the regions
180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
182
183 scenesGroup.ForEachScene(delegate(Scene scene)
184 {
185 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
186 ArchiveOneRegion(scene, regionDir, assetUuids);
187 });
188
189 // Archive the assets
190
191 if (SaveAssets)
192 {
193 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
194
195 // Asynchronously request all the assets required to perform this archive operation
196 AssetsRequest ar
197 = new AssetsRequest(
198 new AssetsArchiver(m_archiveWriter), assetUuids,
199 m_rootScene.AssetService, m_rootScene.UserAccountService,
200 m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
201
202 Util.FireAndForget(o => ar.Execute());
203
204 // CloseArchive() will be called from ReceivedAllAssets()
205 }
206 else
207 {
208 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
209 CloseArchive(string.Empty);
210 }
211 }
212 catch (Exception e)
213 {
214 CloseArchive(e.Message);
215 throw;
216 }
217 }
218
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
223
224 EntityBase[] entities = scene.GetEntities();
225 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
226
227 int numObjectsSkippedPermissions = 0;
228
229 // Filter entities so that we only have scene objects.
230 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
231 // end up having to do this
232 IPermissionsModule permissionsModule = scene.RequestModuleInterface<IPermissionsModule>();
233 foreach (EntityBase entity in entities)
234 {
235 if (entity is SceneObjectGroup)
236 {
237 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
238
239 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
240 {
241 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule))
242 {
243 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
244 ++numObjectsSkippedPermissions;
245 }
246 else
247 {
248 sceneObjects.Add(sceneObject);
249 }
250 }
251 }
252 }
253
254 if (SaveAssets)
255 {
256 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService);
257 int prevAssets = assetUuids.Count;
258
259 foreach (SceneObjectGroup sceneObject in sceneObjects)
260 {
261 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
262 }
263
264 m_log.DebugFormat(
265 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
266 sceneObjects.Count, assetUuids.Count - prevAssets);
267 }
268
269 if (numObjectsSkippedPermissions > 0)
270 {
271 m_log.DebugFormat(
272 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
273 numObjectsSkippedPermissions);
274 }
275
276 // Make sure that we also request terrain texture assets
277 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
278
279 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
280 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
281
282 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
283 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
284
285 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
286 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
287
288 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
289 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
290
291 Save(scene, sceneObjects, regionDir);
292 }
293
294 /// <summary>
295 /// Checks whether the user has permission to export an object group to an OAR.
296 /// </summary>
297 /// <param name="user">The user</param>
298 /// <param name="objGroup">The object group</param>
299 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
300 /// <param name="permissionsModule">The scene's permissions module</param>
301 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
302 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule)
303 {
304 if (checkPermissions == null)
305 return true;
306
307 if (permissionsModule == null)
308 return true; // this shouldn't happen
309
310 // Check whether the user is permitted to export all of the parts in the SOG. If any
311 // part can't be exported then the entire SOG can't be exported.
312
313 bool permitted = true;
314 //int primNumber = 1;
315
316 foreach (SceneObjectPart obj in objGroup.Parts)
317 {
318 uint perm;
319 PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj);
320 switch (permissionClass)
321 {
322 case PermissionClass.Owner:
323 perm = obj.BaseMask;
324 break;
325 case PermissionClass.Group:
326 perm = obj.GroupMask | obj.EveryoneMask;
327 break;
328 case PermissionClass.Everyone:
329 default:
330 perm = obj.EveryoneMask;
331 break;
332 }
333
334 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
335 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
336
337 // Special case: if Everyone can copy the object then this implies it can also be
338 // Transferred.
339 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
340 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
341 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
342 if (permissionClass != PermissionClass.Owner)
343 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
344
345 bool partPermitted = true;
346 if (checkPermissions.Contains("C") && !canCopy)
347 partPermitted = false;
348 if (checkPermissions.Contains("T") && !canTransfer)
349 partPermitted = false;
350
351 // If the user is the Creator of the object then it can always be included in the OAR
352 bool creator = (obj.CreatorID.Guid == user.Guid);
353 if (creator)
354 partPermitted = true;
355
356 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
357 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
358 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
359 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
360
361 if (!partPermitted)
362 {
363 permitted = false;
364 break;
365 }
366
367 //++primNumber;
368 }
369
370 return permitted;
371 }
372
373 /// <summary>
374 /// Create the control file.
375 /// </summary>
376 /// <returns></returns>
377 public string CreateControlFile(ArchiveScenesGroup scenesGroup)
378 {
379 int majorVersion;
380 int minorVersion;
381
382 if (MultiRegionFormat)
383 {
384 majorVersion = MAX_MAJOR_VERSION;
385 minorVersion = 0;
386 }
387 else
388 {
389 // To support older versions of OpenSim, we continue to create single-region OARs
390 // using the old file format. In the future this format will be discontinued.
391 majorVersion = 0;
392 minorVersion = 8;
393 }
394//
395// if (m_options.ContainsKey("version"))
396// {
397// string[] parts = m_options["version"].ToString().Split('.');
398// if (parts.Length >= 1)
399// {
400// majorVersion = Int32.Parse(parts[0]);
401//
402// if (parts.Length >= 2)
403// minorVersion = Int32.Parse(parts[1]);
404// }
405// }
406//
407// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
408// {
409// throw new Exception(
410// string.Format(
411// "OAR version number for save must be between {0} and {1}",
412// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
413// }
414// else if (majorVersion == MAX_MAJOR_VERSION)
415// {
416// // Force 1.0
417// minorVersion = 0;
418// }
419// else if (majorVersion == MIN_MAJOR_VERSION)
420// {
421// // Force 0.4
422// minorVersion = 4;
423// }
424
425 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
426 if (majorVersion == 1)
427 {
428 m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR");
429 }
430
431 String s;
432
433 using (StringWriter sw = new StringWriter())
434 {
435 using (XmlTextWriter xtw = new XmlTextWriter(sw))
436 {
437 xtw.Formatting = Formatting.Indented;
438 xtw.WriteStartDocument();
439 xtw.WriteStartElement("archive");
440 xtw.WriteAttributeString("major_version", majorVersion.ToString());
441 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
442
443 xtw.WriteStartElement("creation_info");
444 DateTime now = DateTime.UtcNow;
445 TimeSpan t = now - new DateTime(1970, 1, 1);
446 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
447 if (!MultiRegionFormat)
448 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
449 xtw.WriteEndElement();
450
451 xtw.WriteElementString("assets_included", SaveAssets.ToString());
452
453 if (MultiRegionFormat)
454 {
455 WriteRegionsManifest(scenesGroup, xtw);
456 }
457 else
458 {
459 xtw.WriteStartElement("region_info");
460 WriteRegionInfo(m_rootScene, xtw);
461 xtw.WriteEndElement();
462 }
463
464 xtw.WriteEndElement();
465
466 xtw.Flush();
467 }
468
469 s = sw.ToString();
470 }
471
472 return s;
473 }
474
475 /// <summary>
476 /// Writes the list of regions included in a multi-region OAR.
477 /// </summary>
478 private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw)
479 {
480 xtw.WriteStartElement("regions");
481
482 // Write the regions in order: rows from South to North, then regions from West to East.
483 // The list of regions can have "holes"; we write empty elements in their position.
484
485 for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y)
486 {
487 SortedDictionary<uint, Scene> row;
488 if (scenesGroup.Regions.TryGetValue(y, out row))
489 {
490 xtw.WriteStartElement("row");
491
492 for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x)
493 {
494 Scene scene;
495 if (row.TryGetValue(x, out scene))
496 {
497 xtw.WriteStartElement("region");
498 xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString());
499 xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID));
500 WriteRegionInfo(scene, xtw);
501 xtw.WriteEndElement();
502 }
503 else
504 {
505 // Write a placeholder for a missing region
506 xtw.WriteElementString("region", "");
507 }
508 }
509
510 xtw.WriteEndElement();
511 }
512 else
513 {
514 // Write a placeholder for a missing row
515 xtw.WriteElementString("row", "");
516 }
517 }
518
519 xtw.WriteEndElement(); // "regions"
520 }
521
522 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
523 {
524 bool isMegaregion;
525 Vector2 size;
526
527 IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>();
528
529 if (rcMod != null)
530 isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
531 else
532 isMegaregion = false;
533
534 if (isMegaregion)
535 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
536 else
537 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
538
539 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 }
542
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 {
546 if (regionDir != string.Empty)
547 regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/";
548
549 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
550
551 // Write out region settings
552 string settingsPath = String.Format("{0}{1}{2}.xml",
553 regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName);
554 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings));
555
556 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
557
558 // Write out land data (aka parcel) settings
559 List<ILandObject> landObjects = scene.LandChannel.AllParcels();
560 foreach (ILandObject lo in landObjects)
561 {
562 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml",
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString());
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 }
567
568 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
569
570 // Write out terrain
571 string terrainPath = String.Format("{0}{1}{2}.r32",
572 regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName);
573
574 MemoryStream ms = new MemoryStream();
575 scene.RequestModuleInterface<ITerrainModule>().SaveToStream(terrainPath, ms);
576 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
577 ms.Close();
578
579 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
580
581 // Write out scene object metadata
582 IRegionSerialiserModule serializer = scene.RequestModuleInterface<IRegionSerialiserModule>();
583 foreach (SceneObjectGroup sceneObject in sceneObjects)
584 {
585 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
586
587 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
588 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
589 m_archiveWriter.WriteFile(objectPath, serializedObject);
590 }
591 }
592
593 protected void ReceivedAllAssets(
594 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
595 {
596 foreach (UUID uuid in assetsNotFoundUuids)
597 {
598 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
599 }
600
601 // m_log.InfoFormat(
602 // "[ARCHIVER]: Received {0} of {1} assets requested",
603 // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
604
605 CloseArchive(String.Empty);
606 }
607
608
609 /// <summary>
610 /// Closes the archive and notifies that we're done.
611 /// </summary>
612 /// <param name="errorMessage">The error that occurred, or empty for success</param>
613 protected void CloseArchive(string errorMessage)
614 {
615 try
616 {
617 if (m_archiveWriter != null)
618 m_archiveWriter.Close();
619 m_saveStream.Close();
620 }
621 catch (Exception e)
622 {
623 m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e);
624 if (errorMessage == string.Empty)
625 errorMessage = e.Message;
626 }
627
628 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
629
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 }
632
633 }
634}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
new file mode 100644
index 0000000..0780d86
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
@@ -0,0 +1,153 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.CoreModules.World.Terrain;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.CoreModules.World.Archiver
43{
44 /// <summary>
45 /// Method called when all the necessary assets for an archive request have been received.
46 /// </summary>
47 public delegate void AssetsRequestCallback(
48 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
49
50 /// <summary>
51 /// Execute the write of an archive once we have received all the necessary data
52 /// </summary>
53 public class ArchiveWriteRequestExecution
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 protected ITerrainModule m_terrainModule;
58 protected IRegionSerialiserModule m_serialiser;
59 protected List<SceneObjectGroup> m_sceneObjects;
60 protected Scene m_scene;
61 protected TarArchiveWriter m_archiveWriter;
62 protected Guid m_requestId;
63 protected Dictionary<string, object> m_options;
64
65 public ArchiveWriteRequestExecution(
66 List<SceneObjectGroup> sceneObjects,
67 ITerrainModule terrainModule,
68 IRegionSerialiserModule serialiser,
69 Scene scene,
70 TarArchiveWriter archiveWriter,
71 Guid requestId,
72 Dictionary<string, object> options)
73 {
74 m_sceneObjects = sceneObjects;
75 m_terrainModule = terrainModule;
76 m_serialiser = serialiser;
77 m_scene = scene;
78 m_archiveWriter = archiveWriter;
79 m_requestId = requestId;
80 m_options = options;
81 }
82
83 protected internal void ReceivedAllAssets(
84 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
85 {
86 try
87 {
88 Save(assetsFoundUuids, assetsNotFoundUuids);
89 }
90 finally
91 {
92 m_archiveWriter.Close();
93 }
94
95 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName);
96
97 m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty);
98 }
99
100 protected internal void Save(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
101 {
102 foreach (UUID uuid in assetsNotFoundUuids)
103 {
104 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
105 }
106
107// m_log.InfoFormat(
108// "[ARCHIVER]: Received {0} of {1} assets requested",
109// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
110
111 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
112
113 // Write out region settings
114 string settingsPath
115 = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName);
116 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings));
117
118 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
119
120 // Write out land data (aka parcel) settings
121 List<ILandObject>landObjects = m_scene.LandChannel.AllParcels();
122 foreach (ILandObject lo in landObjects)
123 {
124 LandData landData = lo.LandData;
125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
126 landData.GlobalID.ToString());
127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
128 }
129
130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
131
132 // Write out terrain
133 string terrainPath
134 = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName);
135
136 MemoryStream ms = new MemoryStream();
137 m_terrainModule.SaveToStream(terrainPath, ms);
138 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
139 ms.Close();
140
141 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
142
143 // Write out scene object metadata
144 foreach (SceneObjectGroup sceneObject in m_sceneObjects)
145 {
146 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
147
148 string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options);
149 m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject);
150 }
151 }
152 }
153} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
new file mode 100644
index 0000000..4edaaca
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -0,0 +1,438 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46
47namespace OpenSim.Region.CoreModules.World.Archiver
48{
49 /// <summary>
50 /// Prepare to write out an archive.
51 /// </summary>
52 public class ArchiveWriteRequestPreparation
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 /// <summary>
57 /// The minimum major version of OAR that we can write.
58 /// </summary>
59 public static int MIN_MAJOR_VERSION = 0;
60
61 /// <summary>
62 /// The maximum major version of OAR that we can write.
63 /// </summary>
64 public static int MAX_MAJOR_VERSION = 0;
65
66 /// <summary>
67 /// Determine whether this archive will save assets. Default is true.
68 /// </summary>
69 public bool SaveAssets { get; set; }
70
71 protected ArchiverModule m_module;
72 protected Scene m_scene;
73 protected Stream m_saveStream;
74 protected Guid m_requestId;
75
76 /// <summary>
77 /// Constructor
78 /// </summary>
79 /// <param name="module">Calling module</param>
80 /// <param name="savePath">The path to which to save data.</param>
81 /// <param name="requestId">The id associated with this request</param>
82 /// <exception cref="System.IO.IOException">
83 /// If there was a problem opening a stream for the file specified by the savePath
84 /// </exception>
85 public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
86 {
87 try
88 {
89 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
90 }
91 catch (EntryPointNotFoundException e)
92 {
93 m_log.ErrorFormat(
94 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
95 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
96 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
97 }
98 }
99
100 /// <summary>
101 /// Constructor.
102 /// </summary>
103 /// <param name="module">Calling module</param>
104 /// <param name="saveStream">The stream to which to save data.</param>
105 /// <param name="requestId">The id associated with this request</param>
106 public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
107 {
108 m_saveStream = saveStream;
109 }
110
111 protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
112 {
113 m_module = module;
114
115 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
116 // this.
117 if (m_module != null)
118 m_scene = m_module.Scene;
119
120 m_requestId = requestId;
121
122 SaveAssets = true;
123 }
124
125 /// <summary>
126 /// Archive the region requested.
127 /// </summary>
128 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
129 public void ArchiveRegion(Dictionary<string, object> options)
130 {
131 if (options.ContainsKey("noassets") && (bool)options["noassets"])
132 SaveAssets = false;
133
134 try
135 {
136 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
137
138 EntityBase[] entities = m_scene.GetEntities();
139 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
140
141 string checkPermissions = null;
142 int numObjectsSkippedPermissions = 0;
143 Object temp;
144 if (options.TryGetValue("checkPermissions", out temp))
145 checkPermissions = (string)temp;
146
147 // Filter entities so that we only have scene objects.
148 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
149 // end up having to do this
150 foreach (EntityBase entity in entities)
151 {
152 if (entity is SceneObjectGroup)
153 {
154 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
155
156 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
157 {
158 if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
159 {
160 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
161 ++numObjectsSkippedPermissions;
162 }
163 else
164 {
165 sceneObjects.Add(sceneObject);
166 }
167 }
168 }
169 }
170
171 if (SaveAssets)
172 {
173 UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService);
174
175 foreach (SceneObjectGroup sceneObject in sceneObjects)
176 {
177 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
178 }
179
180 m_log.DebugFormat(
181 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
182 sceneObjects.Count, assetUuids.Count);
183 }
184 else
185 {
186 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
187 }
188
189 if (numObjectsSkippedPermissions > 0)
190 {
191 m_log.DebugFormat(
192 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
193 numObjectsSkippedPermissions);
194 }
195
196 // Make sure that we also request terrain texture assets
197 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
198
199 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
200 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
201
202 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
203 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
204
205 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
206 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
207
208 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
209 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
210
211 TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream);
212
213 // Asynchronously request all the assets required to perform this archive operation
214 ArchiveWriteRequestExecution awre
215 = new ArchiveWriteRequestExecution(
216 sceneObjects,
217 m_scene.RequestModuleInterface<ITerrainModule>(),
218 m_scene.RequestModuleInterface<IRegionSerialiserModule>(),
219 m_scene,
220 archiveWriter,
221 m_requestId,
222 options);
223
224 m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time.");
225
226 // Write out control file. This has to be done first so that subsequent loaders will see this file first
227 // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
228 archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));
229 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
230
231 if (SaveAssets)
232 {
233 AssetsRequest ar
234 = new AssetsRequest(
235 new AssetsArchiver(archiveWriter), assetUuids,
236 m_scene.AssetService, m_scene.UserAccountService,
237 m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets);
238
239 Util.FireAndForget(o => ar.Execute());
240 }
241 else
242 {
243 awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>());
244 }
245 }
246 catch (Exception)
247 {
248 m_saveStream.Close();
249 throw;
250 }
251 }
252
253 /// <summary>
254 /// Checks whether the user has permission to export an object group to an OAR.
255 /// </summary>
256 /// <param name="user">The user</param>
257 /// <param name="objGroup">The object group</param>
258 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
259 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
260 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
261 {
262 if (checkPermissions == null)
263 return true;
264
265 IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
266 if (module == null)
267 return true; // this shouldn't happen
268
269 // Check whether the user is permitted to export all of the parts in the SOG. If any
270 // part can't be exported then the entire SOG can't be exported.
271
272 bool permitted = true;
273 //int primNumber = 1;
274
275 foreach (SceneObjectPart obj in objGroup.Parts)
276 {
277 uint perm;
278 PermissionClass permissionClass = module.GetPermissionClass(user, obj);
279 switch (permissionClass)
280 {
281 case PermissionClass.Owner:
282 perm = obj.BaseMask;
283 break;
284 case PermissionClass.Group:
285 perm = obj.GroupMask | obj.EveryoneMask;
286 break;
287 case PermissionClass.Everyone:
288 default:
289 perm = obj.EveryoneMask;
290 break;
291 }
292
293 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
294 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
295
296 // Special case: if Everyone can copy the object then this implies it can also be
297 // Transferred.
298 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
299 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
300 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
301 if (permissionClass != PermissionClass.Owner)
302 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
303
304 bool partPermitted = true;
305 if (checkPermissions.Contains("C") && !canCopy)
306 partPermitted = false;
307 if (checkPermissions.Contains("T") && !canTransfer)
308 partPermitted = false;
309
310 // If the user is the Creator of the object then it can always be included in the OAR
311 bool creator = (obj.CreatorID.Guid == user.Guid);
312 if (creator)
313 partPermitted = true;
314
315 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
316 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
317 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
318 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
319
320 if (!partPermitted)
321 {
322 permitted = false;
323 break;
324 }
325
326 //++primNumber;
327 }
328
329 return permitted;
330 }
331
332 /// <summary>
333 /// Create the control file for the most up to date archive
334 /// </summary>
335 /// <returns></returns>
336 public string CreateControlFile(Dictionary<string, object> options)
337 {
338 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8;
339//
340// if (options.ContainsKey("version"))
341// {
342// string[] parts = options["version"].ToString().Split('.');
343// if (parts.Length >= 1)
344// {
345// majorVersion = Int32.Parse(parts[0]);
346//
347// if (parts.Length >= 2)
348// minorVersion = Int32.Parse(parts[1]);
349// }
350// }
351//
352// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
353// {
354// throw new Exception(
355// string.Format(
356// "OAR version number for save must be between {0} and {1}",
357// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
358// }
359// else if (majorVersion == MAX_MAJOR_VERSION)
360// {
361// // Force 1.0
362// minorVersion = 0;
363// }
364// else if (majorVersion == MIN_MAJOR_VERSION)
365// {
366// // Force 0.4
367// minorVersion = 4;
368// }
369
370 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
371 //if (majorVersion == 1)
372 //{
373 // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
374 //}
375
376 String s;
377
378 using (StringWriter sw = new StringWriter())
379 {
380 using (XmlTextWriter xtw = new XmlTextWriter(sw))
381 {
382 xtw.Formatting = Formatting.Indented;
383 xtw.WriteStartDocument();
384 xtw.WriteStartElement("archive");
385 xtw.WriteAttributeString("major_version", majorVersion.ToString());
386 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
387
388 xtw.WriteStartElement("creation_info");
389 DateTime now = DateTime.UtcNow;
390 TimeSpan t = now - new DateTime(1970, 1, 1);
391 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
392 xtw.WriteElementString("id", UUID.Random().ToString());
393 xtw.WriteEndElement();
394
395 xtw.WriteStartElement("region_info");
396
397 bool isMegaregion;
398 Vector2 size;
399 IRegionCombinerModule rcMod = null;
400
401 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
402 // this, possibly by doing control file creation somewhere else.
403 if (m_module != null)
404 rcMod = m_module.RegionCombinerModule;
405
406 if (rcMod != null)
407 isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
408 else
409 isMegaregion = false;
410
411 if (isMegaregion)
412 size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
413 else
414 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
415
416 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
417 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
418
419 xtw.WriteEndElement();
420
421 xtw.WriteElementString("assets_included", SaveAssets.ToString());
422
423 xtw.WriteEndElement();
424
425 xtw.Flush();
426 }
427
428 s = sw.ToString();
429 }
430
431// if (m_scene != null)
432// Console.WriteLine(
433// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
434
435 return s;
436 }
437 }
438}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index abf3713..bf3b124 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -32,8 +32,6 @@ using System.Reflection;
32using log4net; 32using log4net;
33using NDesk.Options; 33using NDesk.Options;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
39 37
@@ -119,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
119// 117//
120// foreach (string param in mainParams) 118// foreach (string param in mainParams)
121// m_log.DebugFormat("GOT PARAM [{0}]", param); 119// m_log.DebugFormat("GOT PARAM [{0}]", param);
122 120
123 if (mainParams.Count > 2) 121 if (mainParams.Count > 2)
124 { 122 {
125 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); 123 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
@@ -148,22 +146,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
148 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 146 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
149 ops.Add("publish", v => options["wipe-owners"] = v != null); 147 ops.Add("publish", v => options["wipe-owners"] = v != null);
150 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); 148 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
151 ops.Add("all", delegate(string v) { options["all"] = v != null; });
152 149
153 List<string> mainParams = ops.Parse(cmdparams); 150 List<string> mainParams = ops.Parse(cmdparams);
154 151
155 string path;
156 if (mainParams.Count > 2) 152 if (mainParams.Count > 2)
157 path = mainParams[2]; 153 {
154 ArchiveRegion(mainParams[2], options);
155 }
158 else 156 else
159 path = DEFAULT_OAR_BACKUP_FILENAME; 157 {
160 158 ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options);
161 // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is 159 }
162 // needed
163// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path))
164// return;
165
166 ArchiveRegion(path, options);
167 } 160 }
168 161
169 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 162 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
@@ -176,7 +169,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
176 m_log.InfoFormat( 169 m_log.InfoFormat(
177 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 170 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
178 171
179 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); 172 new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options);
180 } 173 }
181 174
182 public void ArchiveRegion(Stream saveStream) 175 public void ArchiveRegion(Stream saveStream)
@@ -191,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
191 184
192 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) 185 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
193 { 186 {
194 new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); 187 new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options);
195 } 188 }
196 189
197 public void DearchiveRegion(string loadPath) 190 public void DearchiveRegion(string loadPath)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index e2f8833..89e9593 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -46,12 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 /// <summary>
50 /// Method called when all the necessary assets for an archive request have been received.
51 /// </summary>
52 public delegate void AssetsRequestCallback(
53 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
54
55 enum RequestState 49 enum RequestState
56 { 50 {
57 Initial, 51 Initial,
@@ -129,10 +123,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
129 m_options = options; 123 m_options = options;
130 m_repliesRequired = uuids.Count; 124 m_repliesRequired = uuids.Count;
131 125
132 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
133 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
134 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
135 // radical change
136 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); 126 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
137 m_requestCallbackTimer.AutoReset = false; 127 m_requestCallbackTimer.AutoReset = false;
138 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); 128 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
deleted file mode 100644
index 3dcc020..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35using log4net;
36using System.Reflection;
37using OpenSim.Framework.Serialization;
38
39namespace OpenSim.Region.CoreModules.World.Archiver
40{
41 /// <summary>
42 /// The regions included in an OAR file.
43 /// </summary>
44 public class DearchiveScenesInfo
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// One region in the archive.
50 /// </summary>
51 public class RegionInfo
52 {
53 /// <summary>
54 /// The subdirectory in which the region is stored.
55 /// </summary>
56 public string Directory { get; set; }
57
58 /// <summary>
59 /// The region's coordinates (relative to the South-West corner of the block).
60 /// </summary>
61 public Point Location { get; set; }
62
63 /// <summary>
64 /// The UUID of the original scene from which this archived region was saved.
65 /// </summary>
66 public string OriginalID { get; set; }
67
68 /// <summary>
69 /// The scene in the current simulator into which this region is loaded.
70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded.
71 /// </summary>
72 public Scene Scene { get; set; }
73 }
74
75 /// <summary>
76 /// Whether this archive uses the multi-region format.
77 /// </summary>
78 public Boolean MultiRegionFormat { get; set; }
79
80 /// <summary>
81 /// Maps (Region directory -> region)
82 /// </summary>
83 protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>();
84
85 /// <summary>
86 /// Maps (UUID of the scene in the simulator where the region will be loaded -> region)
87 /// </summary>
88 protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>();
89
90 public int LoadedCreationDateTime { get; set; }
91 public string DefaultOriginalID { get; set; }
92
93 // These variables are used while reading the archive control file
94 protected int? m_curY = null;
95 protected int? m_curX = null;
96 protected RegionInfo m_curRegion;
97
98
99 public DearchiveScenesInfo()
100 {
101 MultiRegionFormat = false;
102 }
103
104
105 // The following methods are used while reading the archive control file
106
107 public void StartRow()
108 {
109 m_curY = (m_curY == null) ? 0 : m_curY + 1;
110 m_curX = null;
111 }
112
113 public void StartRegion()
114 {
115 m_curX = (m_curX == null) ? 0 : m_curX + 1;
116 // Note: this doesn't mean we have a real region in this location; this could just be a "hole"
117 }
118
119 public void SetRegionOriginalID(string id)
120 {
121 m_curRegion = new RegionInfo();
122 m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
123 m_curRegion.OriginalID = id;
124 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
125 }
126
127 public void SetRegionDirectory(string directory)
128 {
129 m_curRegion.Directory = directory;
130 m_directory2region[directory] = m_curRegion;
131 }
132
133
134 /// <summary>
135 /// Sets all the scenes present in the simulator.
136 /// </summary>
137 /// <remarks>
138 /// This method matches regions in the archive to scenes in the simulator according to
139 /// their relative position. We only load regions if there's an existing Scene in the
140 /// grid location where the region should be loaded.
141 /// </remarks>
142 /// <param name="rootScene">The scene where the Load OAR operation was run</param>
143 /// <param name="simulatorScenes">All the scenes in the simulator</param>
144 public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes)
145 {
146 foreach (RegionInfo archivedRegion in m_directory2region.Values)
147 {
148 Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY);
149 location.Offset(archivedRegion.Location);
150
151 Scene scene;
152 if (simulatorScenes.TryGetScene(location, out scene))
153 {
154 archivedRegion.Scene = scene;
155 m_newId2region[scene.RegionInfo.RegionID] = archivedRegion;
156 }
157 else
158 {
159 m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}",
160 archivedRegion.Directory, location.X, location.Y);
161 }
162 }
163 }
164
165 /// <summary>
166 /// Returns the archived region according to the path of a file in the archive.
167 /// Also, converts the full path into a path that is relative to the region's directory.
168 /// </summary>
169 /// <param name="fullPath">The path of a file in the archive</param>
170 /// <param name="scene">The corresponding Scene, or null if none</param>
171 /// <param name="relativePath">The path relative to the region's directory. (Or the original
172 /// path, if this file doesn't belong to a region.)</param>
173 /// <returns>True: use this file; False: skip it</returns>
174 public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath)
175 {
176 scene = null;
177 relativePath = fullPath;
178
179 if (!MultiRegionFormat)
180 {
181 if (m_newId2region.Count > 0)
182 scene = m_newId2region.First().Value.Scene;
183 return true;
184 }
185
186 if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH))
187 return true; // this file doesn't belong to a region
188
189 string[] parts = fullPath.Split(new Char[] { '/' }, 3);
190 if (parts.Length != 3)
191 return false;
192 string regionDirectory = parts[1];
193 relativePath = parts[2];
194
195 RegionInfo region;
196 if (m_directory2region.TryGetValue(regionDirectory, out region))
197 {
198 scene = region.Scene;
199 return (scene != null);
200 }
201 else
202 {
203 return false;
204 }
205 }
206
207 /// <summary>
208 /// Returns the original UUID of a region (from the simulator where the OAR was saved),
209 /// given the UUID of the scene it was loaded into in the current simulator.
210 /// </summary>
211 /// <param name="newID"></param>
212 /// <returns></returns>
213 public string GetOriginalRegionID(UUID newID)
214 {
215 RegionInfo region;
216 if (m_newId2region.TryGetValue(newID, out region))
217 return region.OriginalID;
218 else
219 return DefaultOriginalID;
220 }
221
222 /// <summary>
223 /// Returns the scenes that have been (or will be) loaded.
224 /// </summary>
225 /// <returns></returns>
226 public List<UUID> GetLoadedScenes()
227 {
228 return m_newId2region.Keys.ToList();
229 }
230
231 }
232}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 82f49b0..5deaf52 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -47,41 +47,32 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; 47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader;
48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; 48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter;
49using RegionSettings = OpenSim.Framework.RegionSettings; 49using RegionSettings = OpenSim.Framework.RegionSettings;
50using OpenSim.Region.Framework.Interfaces;
51 50
52namespace OpenSim.Region.CoreModules.World.Archiver.Tests 51namespace OpenSim.Region.CoreModules.World.Archiver.Tests
53{ 52{
54 [TestFixture] 53 [TestFixture]
55 public class ArchiverTests : OpenSimTestCase 54 public class ArchiverTests
56 { 55 {
57 private Guid m_lastRequestId; 56 private Guid m_lastRequestId;
58 private string m_lastErrorMessage; 57 private string m_lastErrorMessage;
59 58
60 protected SceneHelpers m_sceneHelpers;
61 protected TestScene m_scene; 59 protected TestScene m_scene;
62 protected ArchiverModule m_archiverModule; 60 protected ArchiverModule m_archiverModule;
63 protected SerialiserModule m_serialiserModule;
64 61
65 protected TaskInventoryItem m_soundItem; 62 protected TaskInventoryItem m_soundItem;
66 63
67 [SetUp] 64 [SetUp]
68 public override void SetUp() 65 public void SetUp()
69 { 66 {
70 base.SetUp();
71
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
75 m_archiverModule = new ArchiverModule(); 67 m_archiverModule = new ArchiverModule();
76 m_serialiserModule = new SerialiserModule(); 68 SerialiserModule serialiserModule = new SerialiserModule();
77 TerrainModule terrainModule = new TerrainModule(); 69 TerrainModule terrainModule = new TerrainModule();
78 70
79 m_sceneHelpers = new SceneHelpers(); 71 m_scene = new SceneHelpers().SetupScene();
80 m_scene = m_sceneHelpers.SetupScene(); 72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule);
81 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
82 } 73 }
83 74
84 private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage) 75 private void LoadCompleted(Guid requestId, string errorMessage)
85 { 76 {
86 lock (this) 77 lock (this)
87 { 78 {
@@ -137,10 +128,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
137 TestHelpers.InMethod(); 128 TestHelpers.InMethod();
138// log4net.Config.XmlConfigurator.Configure(); 129// log4net.Config.XmlConfigurator.Configure();
139 130
140 SceneObjectGroup sog1; 131 SceneObjectPart part1 = CreateSceneObjectPart1();
141 SceneObjectGroup sog2; 132 SceneObjectGroup sog1 = new SceneObjectGroup(part1);
142 UUID ncAssetUuid; 133 m_scene.AddNewSceneObject(sog1, false);
143 CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); 134
135 SceneObjectPart part2 = CreateSceneObjectPart2();
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
141 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 part2.Inventory.AddInventoryItem(ncItem, true);
149
150 m_scene.AddNewSceneObject(sog2, false);
144 151
145 MemoryStream archiveWriteStream = new MemoryStream(); 152 MemoryStream archiveWriteStream = new MemoryStream();
146 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 153 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
@@ -179,7 +186,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
179 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 186 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
180 187
181 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 188 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
182 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 189 arr.LoadControlFile(filePath, data);
183 190
184 Assert.That(arr.ControlFileLoaded, Is.True); 191 Assert.That(arr.ControlFileLoaded, Is.True);
185 192
@@ -204,30 +211,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
204 // TODO: Test presence of more files and contents of files. 211 // TODO: Test presence of more files and contents of files.
205 } 212 }
206 213
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
231 /// <summary> 214 /// <summary>
232 /// Test saving an OpenSim Region Archive with the no assets option 215 /// Test saving an OpenSim Region Archive with the no assets option
233 /// </summary> 216 /// </summary>
@@ -287,7 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
287 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 270 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
288 271
289 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 272 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
290 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 273 arr.LoadControlFile(filePath, data);
291 274
292 Assert.That(arr.ControlFileLoaded, Is.True); 275 Assert.That(arr.ControlFileLoaded, Is.True);
293 276
@@ -324,7 +307,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
324 307
325 tar.WriteFile( 308 tar.WriteFile(
326 ArchiveConstants.CONTROL_FILE_PATH, 309 ArchiveConstants.CONTROL_FILE_PATH,
327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 310 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
328 311
329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); 312 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
330 SceneObjectPart sop2 313 SceneObjectPart sop2
@@ -379,10 +362,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
379 // Also check that direct entries which will also have a file entry containing that directory doesn't 362 // Also check that direct entries which will also have a file entry containing that directory doesn't
380 // upset load 363 // upset load
381 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 364 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
382 365
383 tar.WriteFile( 366 tar.WriteFile(
384 ArchiveConstants.CONTROL_FILE_PATH, 367 ArchiveConstants.CONTROL_FILE_PATH,
385 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 368 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
369
386 SceneObjectPart part1 = CreateSceneObjectPart1(); 370 SceneObjectPart part1 = CreateSceneObjectPart1();
387 371
388 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); 372 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
@@ -405,12 +389,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
405 Assert.That(soundDataResourceName, Is.Not.Null); 389 Assert.That(soundDataResourceName, Is.Not.Null);
406 390
407 byte[] soundData; 391 byte[] soundData;
408 UUID soundUuid; 392 Console.WriteLine("Loading " + soundDataResourceName);
409 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); 393 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
410 394 {
411 TaskInventoryItem item1 395 using (BinaryReader br = new BinaryReader(resource))
412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; 396 {
413 part1.Inventory.AddInventoryItem(item1, true); 397 // FIXME: Use the inspector instead
398 soundData = br.ReadBytes(99999999);
399 UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
400 string soundAssetFileName
401 = ArchiveConstants.ASSETS_PATH + soundUuid
402 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
403 tar.WriteFile(soundAssetFileName, soundData);
404
405 /*
406 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
407 scene.AssetService.Store(soundAsset);
408 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
409 */
410
411 TaskInventoryItem item1
412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
413 part1.Inventory.AddInventoryItem(item1, true);
414 }
415 }
416
414 m_scene.AddNewSceneObject(object1, false); 417 m_scene.AddNewSceneObject(object1, false);
415 418
416 string object1FileName = string.Format( 419 string object1FileName = string.Format(
@@ -432,34 +435,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
432 435
433 Assert.That(m_lastErrorMessage, Is.Null); 436 Assert.That(m_lastErrorMessage, Is.Null);
434 437
435 TestLoadedRegion(part1, soundItemName, soundData);
436 }
437
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
439 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
441 {
442 using (BinaryReader br = new BinaryReader(resource))
443 {
444 // FIXME: Use the inspector instead
445 soundData = br.ReadBytes(99999999);
446 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
447 string soundAssetFileName
448 = ArchiveConstants.ASSETS_PATH + soundUuid
449 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
450 tar.WriteFile(soundAssetFileName, soundData);
451
452 /*
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
462 {
463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); 438 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
464 439
465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 440 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
@@ -479,6 +454,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 454 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
480 455
481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 456 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
457
458 // Temporary
459 Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
482 } 460 }
483 461
484 /// <summary> 462 /// <summary>
@@ -538,8 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
538 SerialiserModule serialiserModule = new SerialiserModule(); 516 SerialiserModule serialiserModule = new SerialiserModule();
539 TerrainModule terrainModule = new TerrainModule(); 517 TerrainModule terrainModule = new TerrainModule();
540 518
541 m_sceneHelpers = new SceneHelpers(); 519 TestScene scene2 = new SceneHelpers().SetupScene();
542 TestScene scene2 = m_sceneHelpers.SetupScene();
543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
544 521
545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -577,7 +554,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
577 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 554 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
578 tar.WriteFile( 555 tar.WriteFile(
579 ArchiveConstants.CONTROL_FILE_PATH, 556 ArchiveConstants.CONTROL_FILE_PATH,
580 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 557 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
581 558
582 RegionSettings rs = new RegionSettings(); 559 RegionSettings rs = new RegionSettings();
583 rs.AgentLimit = 17; 560 rs.AgentLimit = 17;
@@ -687,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
687 SerialiserModule serialiserModule = new SerialiserModule(); 664 SerialiserModule serialiserModule = new SerialiserModule();
688 TerrainModule terrainModule = new TerrainModule(); 665 TerrainModule terrainModule = new TerrainModule();
689 666
690 Scene scene = m_sceneHelpers.SetupScene(); 667 Scene scene = new SceneHelpers().SetupScene();
691 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); 668 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
692 669
693 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 670 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
@@ -723,258 +700,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
723 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); 700 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
724 } 701 }
725 } 702 }
726
727 /// <summary>
728 /// Test saving a multi-region OAR.
729 /// </summary>
730 [Test]
731 public void TestSaveMultiRegionOar()
732 {
733 TestHelpers.InMethod();
734
735 // Create test regions
736
737 int WIDTH = 2;
738 int HEIGHT = 2;
739
740 List<Scene> scenes = new List<Scene>();
741
742 // Maps (Directory in OAR file -> scene)
743 Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
744
745 // Maps (Scene -> expected object paths)
746 Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
747
748 // List of expected assets
749 List<UUID> expectedAssets = new List<UUID>();
750
751 for (uint y = 0; y < HEIGHT; y++)
752 {
753 for (uint x = 0; x < WIDTH; x++)
754 {
755 Scene scene;
756 if (x == 0 && y == 0)
757 {
758 scene = m_scene; // this scene was already created in SetUp()
759 }
760 else
761 {
762 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
763 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
764 }
765 scenes.Add(scene);
766
767 string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
768 regionPaths[dir] = scene;
769
770 SceneObjectGroup sog1;
771 SceneObjectGroup sog2;
772 UUID ncAssetUuid;
773
774 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
775
776 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
777 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
778 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
779
780 expectedAssets.Add(ncAssetUuid);
781 }
782 }
783
784
785 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789
790 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
791
792 Dictionary<string, Object> options = new Dictionary<string, Object>();
793 options.Add("all", true);
794
795 lock (this)
796 {
797 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
798 Monitor.Wait(this, 60000);
799 }
800
801
802 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805
806 byte[] archive = archiveWriteStream.ToArray();
807 MemoryStream archiveReadStream = new MemoryStream(archive);
808 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
809
810 Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
811 List<UUID> foundAssets = new List<UUID>();
812
813 foreach (Scene scene in scenes)
814 {
815 foundPaths[scene.RegionInfo.RegionID] = new List<string>();
816 }
817
818 string filePath;
819 TarArchiveReader.TarEntryType tarEntryType;
820
821 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
822 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
823
824 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
825 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
826
827 Assert.That(arr.ControlFileLoaded, Is.True);
828
829 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
830 {
831 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
832 {
833 // Assets are shared, so this file doesn't belong to any specific region.
834 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
835 if (fileName.EndsWith("_notecard.txt"))
836 foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
837 }
838 else
839 {
840 // This file belongs to one of the regions. Find out which one.
841 Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
842 string[] parts = filePath.Split(new Char[] { '/' }, 3);
843 Assert.AreEqual(3, parts.Length);
844 string regionDirectory = parts[1];
845 string relativePath = parts[2];
846 Scene scene = regionPaths[regionDirectory];
847
848 if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
849 {
850 foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
851 }
852 }
853 }
854
855 Assert.AreEqual(scenes.Count, foundPaths.Count);
856 foreach (Scene scene in scenes)
857 {
858 Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
859 }
860
861 Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
862 }
863
864 /// <summary>
865 /// Test loading a multi-region OAR.
866 /// </summary>
867 [Test]
868 public void TestLoadMultiRegionOar()
869 {
870 TestHelpers.InMethod();
871
872 // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
873
874 int WIDTH = 2;
875 int HEIGHT = 2;
876
877 for (uint y = 0; y < HEIGHT; y++)
878 {
879 for (uint x = 0; x < WIDTH; x++)
880 {
881 Scene scene;
882 if (x == 0 && y == 0)
883 {
884 scene = m_scene; // this scene was already created in SetUp()
885 }
886 else
887 {
888 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
889 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
890 }
891 }
892 }
893
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene)
896 {
897 scenesGroup.AddScene(scene);
898 });
899 scenesGroup.CalcSceneLocations();
900
901 // Generate the OAR file
902
903 MemoryStream archiveWriteStream = new MemoryStream();
904 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
905
906 ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
907 writeRequest.MultiRegionFormat = true;
908 tar.WriteFile(
909 ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
910
911 SceneObjectPart part1 = CreateSceneObjectPart1();
912 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
913 part1.SitTargetPosition = new Vector3(1, 2, 3);
914
915 SceneObjectGroup object1 = new SceneObjectGroup(part1);
916
917 // Let's put some inventory items into our object
918 string soundItemName = "sound-item1";
919 UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
920 Type type = GetType();
921 Assembly assembly = type.Assembly;
922 string soundDataResourceName = null;
923 string[] names = assembly.GetManifestResourceNames();
924 foreach (string name in names)
925 {
926 if (name.EndsWith(".Resources.test-sound.wav"))
927 soundDataResourceName = name;
928 }
929 Assert.That(soundDataResourceName, Is.Not.Null);
930
931 byte[] soundData;
932 UUID soundUuid;
933 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
934
935 TaskInventoryItem item1
936 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
937 part1.Inventory.AddInventoryItem(item1, true);
938 m_scene.AddNewSceneObject(object1, false);
939
940 string object1FileName = string.Format(
941 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
942 part1.Name,
943 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
944 part1.UUID);
945 string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
946 tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
947
948 tar.Close();
949
950
951 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene)
954 {
955 scene.DeleteAllSceneObjects();
956 });
957
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]);
960
961
962 // Check thay the OAR file contains the expected data
963
964 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
965
966 lock (this)
967 {
968 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
969 m_archiverModule.DearchiveRegion(archiveReadStream);
970 }
971
972 Assert.That(m_lastErrorMessage, Is.Null);
973
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count);
975
976 TestLoadedRegion(part1, soundItemName, soundData);
977 }
978
979 } 703 }
980} 704}
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 5fd1bce..fdef9d8 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -40,7 +40,6 @@ using OpenMetaverse;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using RegionFlags = OpenMetaverse.RegionFlags;
44 43
45namespace OpenSim.Region.CoreModules.World.Estate 44namespace OpenSim.Region.CoreModules.World.Estate
46{ 45{
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
deleted file mode 100644
index d1f05a7..0000000
--- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
+++ /dev/null
@@ -1,110 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Diagnostics;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenMetaverse.Messages.Linden;
39using OpenSim.Framework;
40using OpenSim.Framework.Capabilities;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Physics.Manager;
48using OpenSim.Services.Interfaces;
49using Caps = OpenSim.Framework.Capabilities.Caps;
50using GridRegion = OpenSim.Services.Interfaces.GridRegion;
51
52namespace OpenSim.Region.CoreModules.World.Land
53{
54 public class DwellModule : IDwellModule, INonSharedRegionModule
55 {
56 private Scene m_scene;
57
58 public Type ReplaceableInterface
59 {
60 get { return typeof(IDwellModule); }
61 }
62
63 public string Name
64 {
65 get { return "DwellModule"; }
66 }
67
68 public void Initialise(IConfigSource source)
69 {
70 }
71
72 public void AddRegion(Scene scene)
73 {
74 m_scene = scene;
75
76 m_scene.EventManager.OnNewClient += OnNewClient;
77 }
78
79 public void RegionLoaded(Scene scene)
80 {
81 }
82
83 public void RemoveRegion(Scene scene)
84 {
85 }
86
87 public void Close()
88 {
89 }
90
91 public void OnNewClient(IClientAPI client)
92 {
93 client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
94 }
95
96 private void ClientOnParcelDwellRequest(int localID, IClientAPI client)
97 {
98 ILandObject parcel = m_scene.LandChannel.GetLandObject(localID);
99 if (parcel == null)
100 return;
101
102 client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell);
103 }
104
105 public int GetDwell(UUID parcelID)
106 {
107 return 0;
108 }
109 }
110}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index b5e2bc3..aae6603 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -927,7 +927,6 @@ namespace OpenSim.Region.CoreModules.World.Land
927 ILandObject newLand = startLandObject.Copy(); 927 ILandObject newLand = startLandObject.Copy();
928 newLand.LandData.Name = newLand.LandData.Name; 928 newLand.LandData.Name = newLand.LandData.Name;
929 newLand.LandData.GlobalID = UUID.Random(); 929 newLand.LandData.GlobalID = UUID.Random();
930 newLand.LandData.Dwell = 0;
931 930
932 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 931 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
933 932
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index d5b2adb..4f06737 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -33,7 +33,6 @@ using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using RegionFlags = OpenMetaverse.RegionFlags;
37 36
38namespace OpenSim.Region.CoreModules.World.Land 37namespace OpenSim.Region.CoreModules.World.Land
39{ 38{
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index cbb3abe..102b4d7 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// without recounting the whole sim. 69 /// without recounting the whole sim.
70 /// 70 ///
71 /// We start out tainted so that the first get call resets the various prim counts. 71 /// We start out tainted so that the first get call resets the various prim counts.
72 /// </value> 72 /// <value>
73 private bool m_Tainted = true; 73 private bool m_Tainted = true;
74 74
75 private Object m_TaintLock = new Object(); 75 private Object m_TaintLock = new Object();
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index ab8f143..09f6758 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -27,12 +27,9 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
32using System.Reflection; 30using System.Reflection;
33using System.Text; 31using System.Text;
34using System.Text.RegularExpressions; 32using System.Text.RegularExpressions;
35using System.Xml;
36using log4net; 33using log4net;
37using Mono.Addins; 34using Mono.Addins;
38using NDesk.Options; 35using NDesk.Options;
@@ -43,7 +40,6 @@ using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
44using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Framework.Scenes.Serialization;
47 43
48namespace OpenSim.Region.CoreModules.World.Objects.Commands 44namespace OpenSim.Region.CoreModules.World.Objects.Commands
49{ 45{
@@ -87,85 +83,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
87 m_console.Commands.AddCommand( 83 m_console.Commands.AddCommand(
88 "Objects", false, "delete object owner", 84 "Objects", false, "delete object owner",
89 "delete object owner <UUID>", 85 "delete object owner <UUID>",
90 "Delete scene objects by owner", 86 "Delete a scene object by owner", HandleDeleteObject);
91 "Command will ask for confirmation before proceeding.",
92 HandleDeleteObject);
93 87
94 m_console.Commands.AddCommand( 88 m_console.Commands.AddCommand(
95 "Objects", false, "delete object creator", 89 "Objects", false, "delete object creator",
96 "delete object creator <UUID>", 90 "delete object creator <UUID>",
97 "Delete scene objects by creator", 91 "Delete a scene object by creator", HandleDeleteObject);
98 "Command will ask for confirmation before proceeding.",
99 HandleDeleteObject);
100 92
101 m_console.Commands.AddCommand( 93 m_console.Commands.AddCommand(
102 "Objects", false, "delete object id", 94 "Objects", false, "delete object uuid",
103 "delete object id <UUID-or-localID>", 95 "delete object uuid <UUID>",
104 "Delete a scene object by uuid or localID", 96 "Delete a scene object by uuid", HandleDeleteObject);
105 HandleDeleteObject);
106 97
107 m_console.Commands.AddCommand( 98 m_console.Commands.AddCommand(
108 "Objects", false, "delete object name", 99 "Objects", false, "delete object name",
109 "delete object name [--regex] <name>", 100 "delete object name [--regex] <name>",
110 "Delete a scene object by name.", 101 "Delete a scene object by name.",
111 "Command will ask for confirmation before proceeding.\n" 102 "If --regex is specified then the name is treatead as a regular expression",
112 + "If --regex is specified then the name is treatead as a regular expression",
113 HandleDeleteObject); 103 HandleDeleteObject);
114 104
115 m_console.Commands.AddCommand( 105 m_console.Commands.AddCommand(
116 "Objects", false, "delete object outside", 106 "Objects", false, "delete object outside",
117 "delete object outside", 107 "delete object outside",
118 "Delete all scene objects outside region boundaries", 108 "Delete all scene objects outside region boundaries", HandleDeleteObject);
119 "Command will ask for confirmation before proceeding.",
120 HandleDeleteObject);
121 109
122 m_console.Commands.AddCommand( 110 m_console.Commands.AddCommand(
123 "Objects", 111 "Objects",
124 false, 112 false,
125 "delete object pos", 113 "show object uuid",
126 "delete object pos <start-coord> to <end-coord>", 114 "show object uuid <UUID>",
127 "Delete scene objects within the given area.", 115 "Show details of a scene object with the given UUID", HandleShowObjectByUuid);
128 ConsoleUtil.CoordHelp,
129 HandleDeleteObject);
130
131 m_console.Commands.AddCommand(
132 "Objects",
133 false,
134 "show object id",
135 "show object id [--full] <UUID-or-localID>",
136 "Show details of a scene object with the given UUID or localID",
137 "The --full option will print out information on all the parts of the object.\n"
138 + "For yet more detailed part information, use the \"show part\" commands.",
139 HandleShowObjectById);
140 116
141 m_console.Commands.AddCommand( 117 m_console.Commands.AddCommand(
142 "Objects", 118 "Objects",
143 false, 119 false,
144 "show object name", 120 "show object name",
145 "show object name [--full] [--regex] <name>", 121 "show object name [--regex] <name>",
146 "Show details of scene objects with the given name.", 122 "Show details of scene objects with the given name.",
147 "The --full option will print out information on all the parts of the object.\n" 123 "If --regex is specified then the name is treatead as a regular expression",
148 + "For yet more detailed part information, use the \"show part\" commands.\n"
149 + "If --regex is specified then the name is treatead as a regular expression.",
150 HandleShowObjectByName); 124 HandleShowObjectByName);
151 125
152 m_console.Commands.AddCommand( 126 m_console.Commands.AddCommand(
153 "Objects", 127 "Objects",
154 false, 128 false,
155 "show object pos", 129 "show part uuid",
156 "show object pos [--full] <start-coord> to <end-coord>", 130 "show part uuid <UUID>",
157 "Show details of scene objects within the given area.", 131 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid);
158 "The --full option will print out information on all the parts of the object.\n"
159 + "For yet more detailed part information, use the \"show part\" commands.\n"
160 + ConsoleUtil.CoordHelp,
161 HandleShowObjectByPos);
162
163 m_console.Commands.AddCommand(
164 "Objects",
165 false,
166 "show part id",
167 "show part id <UUID-or-localID>",
168 "Show details of a scene object part with the given UUID or localID", HandleShowPartById);
169 132
170 m_console.Commands.AddCommand( 133 m_console.Commands.AddCommand(
171 "Objects", 134 "Objects",
@@ -173,28 +136,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
173 "show part name", 136 "show part name",
174 "show part name [--regex] <name>", 137 "show part name [--regex] <name>",
175 "Show details of scene object parts with the given name.", 138 "Show details of scene object parts with the given name.",
176 "If --regex is specified then the name is treated as a regular expression", 139 "If --regex is specified then the name is treatead as a regular expression",
177 HandleShowPartByName); 140 HandleShowPartByName);
178
179 m_console.Commands.AddCommand(
180 "Objects",
181 false,
182 "show part pos",
183 "show part pos <start-coord> to <end-coord>",
184 "Show details of scene object parts within the given area.",
185 ConsoleUtil.CoordHelp,
186 HandleShowPartByPos);
187
188 m_console.Commands.AddCommand(
189 "Objects",
190 false,
191 "dump object id",
192 "dump object id <UUID-or-localID>",
193 "Dump the formatted serialization of the given object to the file <UUID>.xml",
194 "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n"
195 + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n"
196 + "If a local ID is given then the filename used is still that for the UUID",
197 HandleDumpObjectById);
198 } 141 }
199 142
200 public void RemoveRegion(Scene scene) 143 public void RemoveRegion(Scene scene)
@@ -207,75 +150,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
207// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); 150// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
208 } 151 }
209 152
210 /// <summary> 153 private void HandleShowObjectByUuid(string module, string[] cmd)
211 /// Outputs the sogs to console.
212 /// </summary>
213 /// <param name='searchPredicate'></param>
214 /// <param name='showFull'>If true then output all part details. If false then output summary.</param>
215 private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull)
216 {
217 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate);
218
219 StringBuilder sb = new StringBuilder();
220
221 foreach (SceneObjectGroup so in sceneObjects)
222 {
223 AddSceneObjectReport(sb, so, showFull);
224 sb.Append("\n");
225 }
226
227 sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name);
228
229 m_console.OutputFormat(sb.ToString());
230 }
231
232 private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull)
233 {
234 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
235 List<SceneObjectPart> parts = new List<SceneObjectPart>();
236
237 sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate)));
238
239 StringBuilder sb = new StringBuilder();
240
241 foreach (SceneObjectPart part in parts)
242 {
243 AddScenePartReport(sb, part, showFull);
244 sb.Append("\n");
245 }
246
247 sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name);
248
249 m_console.OutputFormat(sb.ToString());
250 }
251
252 private void HandleShowObjectById(string module, string[] cmdparams)
253 { 154 {
254 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 155 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
255 return; 156 return;
256 157
257 bool showFull = false; 158 if (cmd.Length < 4)
258 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
259
260 List<string> mainParams = options.Parse(cmdparams);
261
262 if (mainParams.Count < 4)
263 { 159 {
264 m_console.OutputFormat("Usage: show object uuid <uuid>"); 160 m_console.OutputFormat("Usage: show object uuid <uuid>");
265 return; 161 return;
266 } 162 }
267 163
268 UUID uuid; 164 UUID objectUuid;
269 uint localId; 165 if (!UUID.TryParse(cmd[3], out objectUuid))
270 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) 166 {
167 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
271 return; 168 return;
169 }
272 170
273 SceneObjectGroup so; 171 SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid);
274
275 if (localId != ConsoleUtil.LocalIdNotFound)
276 so = m_scene.GetSceneObjectGroup(localId);
277 else
278 so = m_scene.GetSceneObjectGroup(uuid);
279 172
280 if (so == null) 173 if (so == null)
281 { 174 {
@@ -284,7 +177,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
284 } 177 }
285 178
286 StringBuilder sb = new StringBuilder(); 179 StringBuilder sb = new StringBuilder();
287 AddSceneObjectReport(sb, so, showFull); 180 AddSceneObjectReport(sb, so);
288 181
289 m_console.OutputFormat(sb.ToString()); 182 m_console.OutputFormat(sb.ToString());
290 } 183 }
@@ -294,91 +187,70 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
294 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 187 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
295 return; 188 return;
296 189
297 bool showFull = false;
298 bool useRegex = false; 190 bool useRegex = false;
299 OptionSet options = new OptionSet(); 191 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
300 options.Add("full", v => showFull = v != null );
301 options.Add("regex", v => useRegex = v != null );
302 192
303 List<string> mainParams = options.Parse(cmdparams); 193 List<string> mainParams = options.Parse(cmdparams);
304 194
305 if (mainParams.Count < 4) 195 if (mainParams.Count < 4)
306 { 196 {
307 m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>"); 197 m_console.OutputFormat("Usage: show object name [--regex] <name>");
308 return; 198 return;
309 } 199 }
310 200
311 string name = mainParams[3]; 201 string name = mainParams[3];
312 202
313 Predicate<SceneObjectGroup> searchPredicate; 203 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
204 Action<SceneObjectGroup> searchAction;
314 205
315 if (useRegex) 206 if (useRegex)
316 { 207 {
317 Regex nameRegex = new Regex(name); 208 Regex nameRegex = new Regex(name);
318 searchPredicate = so => nameRegex.IsMatch(so.Name); 209 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
319 } 210 }
320 else 211 else
321 { 212 {
322 searchPredicate = so => so.Name == name; 213 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
323 } 214 }
324 215
325 OutputSogsToConsole(searchPredicate, showFull); 216 m_scene.ForEachSOG(searchAction);
326 }
327
328 private void HandleShowObjectByPos(string module, string[] cmdparams)
329 {
330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
331 return;
332
333 bool showFull = false;
334 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
335
336 List<string> mainParams = options.Parse(cmdparams);
337 217
338 if (mainParams.Count < 5) 218 if (sceneObjects.Count == 0)
339 { 219 {
340 m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>"); 220 m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
341 return; 221 return;
342 } 222 }
343 223
344 Vector3 startVector, endVector; 224 StringBuilder sb = new StringBuilder();
345
346 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
347 return;
348 225
349 Predicate<SceneObjectGroup> searchPredicate 226 foreach (SceneObjectGroup so in sceneObjects)
350 = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); 227 {
228 AddSceneObjectReport(sb, so);
229 sb.Append("\n");
230 }
351 231
352 OutputSogsToConsole(searchPredicate, showFull); 232 m_console.OutputFormat(sb.ToString());
353 } 233 }
354 234
355 private void HandleShowPartById(string module, string[] cmdparams) 235 private void HandleShowPartByUuid(string module, string[] cmd)
356 { 236 {
357 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 237 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
358 return; 238 return;
359 239
360// bool showFull = false; 240 if (cmd.Length < 4)
361 OptionSet options = new OptionSet();
362// options.Add("full", v => showFull = v != null );
363
364 List<string> mainParams = options.Parse(cmdparams);
365
366 if (mainParams.Count < 4)
367 { 241 {
368 m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); 242 m_console.OutputFormat("Usage: show part uuid <uuid>");
369 return; 243 return;
370 } 244 }
371 245
372 UUID objectUuid; 246 UUID objectUuid;
373 uint localId; 247 if (!UUID.TryParse(cmd[3], out objectUuid))
374 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) 248 {
249 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
375 return; 250 return;
251 }
376 252
377 SceneObjectPart sop; 253 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid);
378 if (localId == ConsoleUtil.LocalIdNotFound)
379 sop = m_scene.GetSceneObjectPart(objectUuid);
380 else
381 sop = m_scene.GetSceneObjectPart(localId);
382 254
383 if (sop == null) 255 if (sop == null)
384 { 256 {
@@ -387,239 +259,84 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
387 } 259 }
388 260
389 StringBuilder sb = new StringBuilder(); 261 StringBuilder sb = new StringBuilder();
390 AddScenePartReport(sb, sop, true); 262 AddScenePartReport(sb, sop);
391 263
392 m_console.OutputFormat(sb.ToString()); 264 m_console.OutputFormat(sb.ToString());
393 } 265 }
394 266
395 private void HandleShowPartByPos(string module, string[] cmdparams)
396 {
397 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
398 return;
399
400// bool showFull = false;
401 OptionSet options = new OptionSet();
402// options.Add("full", v => showFull = v != null );
403
404 List<string> mainParams = options.Parse(cmdparams);
405
406 if (mainParams.Count < 5)
407 {
408 m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
409 return;
410 }
411
412 string rawConsoleStartVector = mainParams[3];
413 Vector3 startVector;
414
415 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
416 {
417 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
418 return;
419 }
420
421 string rawConsoleEndVector = mainParams[5];
422 Vector3 endVector;
423
424 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
425 {
426 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
427 return;
428 }
429
430 OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true);
431 }
432
433 private void HandleShowPartByName(string module, string[] cmdparams) 267 private void HandleShowPartByName(string module, string[] cmdparams)
434 { 268 {
435 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 269 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
436 return; 270 return;
437 271
438// bool showFull = false;
439 bool useRegex = false; 272 bool useRegex = false;
440 OptionSet options = new OptionSet(); 273 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
441// options.Add("full", v => showFull = v != null );
442 options.Add("regex", v => useRegex = v != null );
443 274
444 List<string> mainParams = options.Parse(cmdparams); 275 List<string> mainParams = options.Parse(cmdparams);
445 276
446 if (mainParams.Count < 4) 277 if (mainParams.Count < 4)
447 { 278 {
448 m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); 279 m_console.OutputFormat("Usage: show part name [--regex] <name>");
449 return; 280 return;
450 } 281 }
451 282
452 string name = mainParams[3]; 283 string name = mainParams[3];
453 284
454 Predicate<SceneObjectPart> searchPredicate; 285 List<SceneObjectPart> parts = new List<SceneObjectPart>();
286
287 Action<SceneObjectGroup> searchAction;
455 288
456 if (useRegex) 289 if (useRegex)
457 { 290 {
458 Regex nameRegex = new Regex(name); 291 Regex nameRegex = new Regex(name);
459 searchPredicate = sop => nameRegex.IsMatch(sop.Name); 292 searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } });
460 } 293 }
461 else 294 else
462 { 295 {
463 searchPredicate = sop => sop.Name == name; 296 searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } });
464 } 297 }
465 298
466 OutputSopsToConsole(searchPredicate, true); 299 m_scene.ForEachSOG(searchAction);
467 }
468
469 private void HandleDumpObjectById(string module, string[] cmdparams)
470 {
471 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
472 return;
473 300
474 if (cmdparams.Length < 4) 301 if (parts.Count == 0)
475 { 302 {
476 m_console.OutputFormat("Usage: dump object id <UUID-or-localID>"); 303 m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
477 return; 304 return;
478 } 305 }
479 306
480 UUID objectUuid; 307 StringBuilder sb = new StringBuilder();
481 uint localId;
482 if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId))
483 return;
484
485 SceneObjectGroup so;
486 if (localId == ConsoleUtil.LocalIdNotFound)
487 so = m_scene.GetSceneObjectGroup(objectUuid);
488 else
489 so = m_scene.GetSceneObjectGroup(localId);
490 308
491 if (so == null) 309 foreach (SceneObjectPart part in parts)
492 { 310 {
493// m_console.OutputFormat("No part found with uuid {0}", objectUuid); 311 AddScenePartReport(sb, part);
494 return; 312 sb.Append("\n");
495 } 313 }
496 314
497 // In case we found it via local ID. 315 m_console.OutputFormat(sb.ToString());
498 objectUuid = so.UUID;
499
500 string fileName = string.Format("{0}.xml", objectUuid);
501
502 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
503 return;
504
505 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
506 {
507 xtw.Formatting = Formatting.Indented;
508 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
509 }
510
511 m_console.OutputFormat("Object dumped to file {0}", fileName);
512 } 316 }
513 317
514 /// <summary> 318 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so)
515 /// Append a scene object report to an input StringBuilder
516 /// </summary>
517 /// <returns></returns>
518 /// <param name='sb'></param>
519 /// <param name='so'</param>
520 /// <param name='showFull'>
521 /// If true then information on all parts of an object is appended.
522 /// If false then only summary information about an object is appended.
523 /// </param>
524 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull)
525 { 319 {
526 if (showFull) 320 sb.AppendFormat("Name: {0}\n", so.Name);
527 { 321 sb.AppendFormat("Description: {0}\n", so.Description);
528 foreach (SceneObjectPart sop in so.Parts) 322 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName);
529 { 323 sb.AppendFormat("Parts: {0}\n", so.PrimCount);
530 AddScenePartReport(sb, sop, false); 324 sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags);
531 sb.Append("\n");
532 }
533 }
534 else
535 {
536 AddSummarySceneObjectReport(sb, so);
537 }
538 325
539 return sb; 326 return sb;
540 } 327 }
541 328
542 private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) 329 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop)
543 {
544 ConsoleDisplayList cdl = new ConsoleDisplayList();
545 cdl.AddRow("Name", so.Name);
546 cdl.AddRow("Descrition", so.Description);
547 cdl.AddRow("Local ID", so.LocalId);
548 cdl.AddRow("UUID", so.UUID);
549 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
550 cdl.AddRow("Parts", so.PrimCount);
551 cdl.AddRow("Flags", so.RootPart.Flags);
552
553 return sb.Append(cdl.ToString());
554 }
555
556 /// <summary>
557 /// Append a scene object part report to an input StringBuilder
558 /// </summary>
559 /// <returns></returns>
560 /// <param name='sb'></param>
561 /// <param name='sop'</param>
562 /// <param name='showFull'>
563 /// If true then information on each inventory item will be shown.
564 /// If false then only summary inventory information is shown.
565 /// </param>
566 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull)
567 {
568 ConsoleDisplayList cdl = new ConsoleDisplayList();
569 cdl.AddRow("Name", sop.Name);
570 cdl.AddRow("Description", sop.Description);
571 cdl.AddRow("Local ID", sop.LocalId);
572 cdl.AddRow("UUID", sop.UUID);
573 cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name));
574 cdl.AddRow(
575 "Parent",
576 sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID));
577 cdl.AddRow("Link number", sop.LinkNum);
578 cdl.AddRow("Flags", sop.Flags);
579
580 object itemsOutput;
581 if (showFull)
582 {
583 StringBuilder itemsSb = new StringBuilder("\n");
584 itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString();
585 }
586 else
587 {
588 itemsOutput = sop.Inventory.Count;
589 }
590
591
592 cdl.AddRow("Items", itemsOutput);
593
594 return sb.Append(cdl.ToString());
595 }
596
597 private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv)
598 { 330 {
599 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 331 sb.AppendFormat("Name: {0}\n", sop.Name);
600 cdt.Indent = 2; 332 sb.AppendFormat("Description: {0}\n", sop.Description);
601 333 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName);
602 cdt.AddColumn("Name", 50); 334 sb.AppendFormat("Parent: {0}",
603 cdt.AddColumn("Type", 12); 335 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID));
604 cdt.AddColumn("Running", 7); 336 sb.AppendFormat("Link number: {0}\n", sop.LinkNum);
605 cdt.AddColumn("Item UUID", 36); 337 sb.AppendFormat("Flags: {0}\n", sop.Flags);
606 cdt.AddColumn("Asset UUID", 36);
607
608 foreach (TaskInventoryItem item in inv.GetInventoryItems())
609 {
610 bool foundScriptInstance, scriptRunning;
611 foundScriptInstance
612 = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning);
613
614 cdt.AddRow(
615 item.Name,
616 ((InventoryType)item.InvType).ToString(),
617 foundScriptInstance ? scriptRunning.ToString() : "n/a",
618 item.ItemID.ToString(),
619 item.AssetID.ToString());
620 }
621 338
622 return sb.Append(cdt.ToString()); 339 return sb;
623 } 340 }
624 341
625 private void HandleDeleteObject(string module, string[] cmd) 342 private void HandleDeleteObject(string module, string[] cmd)
@@ -681,24 +398,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
681 398
682 break; 399 break;
683 400
684 case "id": 401 case "uuid":
685 UUID uuid; 402 if (!UUID.TryParse(o, out match))
686 uint localId;
687 if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId))
688 return; 403 return;
689 404
690 requireConfirmation = false; 405 requireConfirmation = false;
691 deletes = new List<SceneObjectGroup>(); 406 deletes = new List<SceneObjectGroup>();
692 407
693 SceneObjectGroup so; 408 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
694 if (localId == ConsoleUtil.LocalIdNotFound) 409 {
695 so = m_scene.GetSceneObjectGroup(uuid); 410 if (g.UUID == match && !g.IsAttachment)
696 else 411 deletes.Add(g);
697 so = m_scene.GetSceneObjectGroup(localId); 412 });
698 413
699 if (!so.IsAttachment)
700 deletes.Add(so);
701
702 // if (deletes.Count == 0) 414 // if (deletes.Count == 0)
703 // m_console.OutputFormat("No objects were found with uuid {0}", match); 415 // m_console.OutputFormat("No objects were found with uuid {0}", match);
704 416
@@ -738,10 +450,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
738 450
739 break; 451 break;
740 452
741 case "pos":
742 deletes = GetDeleteCandidatesByPos(module, cmd);
743 break;
744
745 default: 453 default:
746 m_console.OutputFormat("Unrecognized mode {0}", mode); 454 m_console.OutputFormat("Unrecognized mode {0}", mode);
747 return; 455 return;
@@ -756,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
756 string.Format( 464 string.Format(
757 "Are you sure that you want to delete {0} objects from {1}", 465 "Are you sure that you want to delete {0} objects from {1}",
758 deletes.Count, m_scene.RegionInfo.RegionName), 466 deletes.Count, m_scene.RegionInfo.RegionName),
759 "y/N"); 467 "n");
760 468
761 if (response.ToLower() != "y") 469 if (response.ToLower() != "y")
762 { 470 {
@@ -778,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
778 486
779 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) 487 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
780 { 488 {
489 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
490 return null;
491
781 bool useRegex = false; 492 bool useRegex = false;
782 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 493 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
783 494
@@ -811,52 +522,5 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
811 522
812 return sceneObjects; 523 return sceneObjects;
813 } 524 }
814
815 /// <summary>
816 /// Get scene object delete candidates by position
817 /// </summary>
818 /// <param name='module'></param>
819 /// <param name='cmdparams'></param>
820 /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there
821 /// are no objects to delete then the list will be empty./returns>
822 private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams)
823 {
824 if (cmdparams.Length < 5)
825 {
826 m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>");
827 return null;
828 }
829
830 Vector3 startVector, endVector;
831
832 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
833 return null;
834
835 return m_scene.GetSceneObjectGroups().FindAll(
836 so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector));
837 }
838
839 private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector)
840 {
841 string rawConsoleStartVector = rawComponents.Take(1).Single();
842
843 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
844 {
845 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
846 endVector = Vector3.Zero;
847
848 return false;
849 }
850
851 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
852
853 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
854 {
855 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
856 return false;
857 }
858
859 return true;
860 }
861 } 525 }
862} \ No newline at end of file 526} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 513a8f5..14c1a39 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -24,110 +24,56 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System;
28using System.IO;
29using System.Collections.Generic;
30using System.Reflection;
31 27
28using System;
32using Nini.Config; 29using Nini.Config;
33using OpenMetaverse; 30using OpenMetaverse;
34using log4net;
35using Mono.Addins;
36
37using OpenSim.Framework; 31using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using System.Reflection;
35using log4net;
40 36
41namespace OpenSim.Region.CoreModules.World.Sound 37namespace OpenSim.Region.CoreModules.World.Sound
42{ 38{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] 39 public class SoundModule : IRegionModule, ISoundModule
44 public class SoundModule : INonSharedRegionModule, ISoundModule
45 { 40 {
46 private static readonly ILog m_log = LogManager.GetLogger( 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 MethodBase.GetCurrentMethod().DeclaringType); 42
48 43 protected Scene m_scene;
49 private Scene m_scene; 44
50 45 public void Initialise(Scene scene, IConfigSource source)
51 public bool Enabled { get; private set; }
52
53 public float MaxDistance { get; private set; }
54
55 #region INonSharedRegionModule
56
57 public void Initialise(IConfigSource configSource)
58 {
59 IConfig config = configSource.Configs["Sounds"];
60
61 if (config == null)
62 {
63 Enabled = true;
64 MaxDistance = 100.0f;
65 }
66 else
67 {
68 Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
69 Path.GetFileName(Assembly.GetExecutingAssembly().Location)
70 + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
71 MaxDistance = config.GetFloat("MaxDistance", 100.0f);
72 }
73 }
74
75 public void AddRegion(Scene scene) { }
76
77 public void RemoveRegion(Scene scene)
78 { 46 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient;
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84 if (!Enabled)
85 return;
86
87 m_scene = scene; 47 m_scene = scene;
88 m_scene.EventManager.OnClientLogin += OnNewClient; 48
89 49 m_scene.EventManager.OnNewClient += OnNewClient;
50
90 m_scene.RegisterModuleInterface<ISoundModule>(this); 51 m_scene.RegisterModuleInterface<ISoundModule>(this);
91 } 52 }
92 53
93 public void Close() { } 54 public void PostInitialise() {}
94 55 public void Close() {}
95 public Type ReplaceableInterface
96 {
97 get { return typeof(ISoundModule); }
98 }
99
100 public string Name { get { return "Sound Module"; } } 56 public string Name { get { return "Sound Module"; } }
101 57 public bool IsSharedModule { get { return false; } }
102 #endregion 58
103
104 #region Event Handlers
105
106 private void OnNewClient(IClientAPI client) 59 private void OnNewClient(IClientAPI client)
107 { 60 {
108 client.OnSoundTrigger += TriggerSound; 61 client.OnSoundTrigger += TriggerSound;
109 } 62 }
110 63
111 #endregion
112
113 #region ISoundModule
114
115 public virtual void PlayAttachedSound( 64 public virtual void PlayAttachedSound(
116 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) 65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
117 { 66 {
118 SceneObjectPart part; 67 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
119 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 68 if (part == null)
120 return; 69 return;
121 70
122 SceneObjectGroup grp = part.ParentGroup; 71 SceneObjectGroup grp = part.ParentGroup;
123 72
124 if (radius == 0)
125 radius = MaxDistance;
126
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 73 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
128 { 74 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 75 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
130 if (dis > MaxDistance) // Max audio distance 76 if (dis > 100.0) // Max audio distance
131 return; 77 return;
132 78
133 if (grp.IsAttachment) 79 if (grp.IsAttachment)
@@ -140,21 +86,23 @@ namespace OpenSim.Region.CoreModules.World.Sound
140 } 86 }
141 87
142 // Scale by distance 88 // Scale by distance
143 double thisSpGain = gain * ((radius - dis) / radius); 89 if (radius == 0)
90 gain = (float)((double)gain * ((100.0 - dis) / 100.0));
91 else
92 gain = (float)((double)gain * ((radius - dis) / radius));
144 93
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 94 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags);
146 ownerID, (float)thisSpGain, flags);
147 }); 95 });
148 } 96 }
149 97
150 public virtual void TriggerSound( 98 public virtual void TriggerSound(
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 99 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 100 {
153 SceneObjectPart part; 101 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 102 if (part == null)
155 { 103 {
156 ScenePresence sp; 104 ScenePresence sp;
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 105 if (!m_scene.TryGetScenePresence(objectID, out sp))
158 return; 106 return;
159 } 107 }
160 else 108 else
@@ -168,207 +116,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
168 } 116 }
169 } 117 }
170 118
171 if (radius == 0)
172 radius = MaxDistance;
173
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 120 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 122
178 if (dis > MaxDistance) // Max audio distance 123 if (dis > 100.0) // Max audio distance
179 return; 124 return;
180 125
181 // Scale by distance 126 float thisSpGain;
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position,
186 (float)thisSpGain);
187 });
188 }
189
190 public virtual void StopSound(UUID objectID)
191 {
192 SceneObjectPart m_host;
193 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
194 return;
195
196 StopSound(m_host);
197 }
198
199 private static void StopSound(SceneObjectPart m_host)
200 {
201 m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
204 {
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
206 {
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 }
236
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
238 {
239 SceneObjectPart part;
240 if (soundID == UUID.Zero
241 || !m_scene.TryGetSceneObjectPart(objectID, out part))
242 {
243 return;
244 }
245
246 if (radius == 0)
247 radius = MaxDistance;
248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 });
254 }
255
256 // Xantor 20080528 we should do this differently.
257 // 1) apply the sound to the object
258 // 2) schedule full update
259 // just sending the sound out once doesn't work so well when other avatars come in view later on
260 // or when the prim gets moved, changed, sat on, whatever
261 // see large number of mantises (mantes?)
262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster)
266 {
267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return;
270
271 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host;
273
274 if (m_host.Sound != UUID.Zero)
275 StopSound(m_host);
276
277 m_host.Sound = soundID;
278 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping
280 m_host.SoundRadius = radius;
281
282 m_host.ScheduleFullUpdate();
283 m_host.SendFullUpdateToAllClients();
284 }
285
286 public void SendSound(UUID objectID, UUID soundID, double volume,
287 bool triggered, byte flags, float radius, bool useMaster,
288 bool isMaster)
289 {
290 if (soundID == UUID.Zero)
291 return;
292
293 SceneObjectPart part;
294 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
295 return;
296
297 volume = Util.Clip((float)volume, 0, 1);
298
299 UUID parentID = part.ParentGroup.UUID;
300
301 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303
304 if (useMaster)
305 {
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else
334 {
335 if (triggered)
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
337 else
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
339 }
340 }
341
342 public void TriggerSoundLimited(UUID objectID, UUID sound,
343 double volume, Vector3 min, Vector3 max)
344 {
345 if (sound == UUID.Zero)
346 return;
347
348 SceneObjectPart part;
349 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
350 return;
351
352 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
353 {
354 double dis = Util.GetDistanceTo(sp.AbsolutePosition,
355 part.AbsolutePosition);
356
357 if (dis > MaxDistance) // Max audio distance
358 return;
359 else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
360 return;
361 127
362 // Scale by distance 128 // Scale by distance
363 double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); 129 if (radius == 0)
130 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
131 else
132 thisSpGain = (float)((double)gain * ((radius - dis) / radius));
364 133
365 sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, 134 sp.ControllingClient.SendTriggeredSound(
366 part.UUID, part.ParentGroup.UUID, 135 soundId, ownerID, objectID, parentID, handle, position, thisSpGain);
367 m_scene.RegionInfo.RegionHandle,
368 part.AbsolutePosition, (float)thisSpGain);
369 }); 136 });
370 } 137 }
371
372 #endregion
373 } 138 }
374} 139}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index d99567c..402b9fb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -414,7 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
414 private void LoadPlugins() 414 private void LoadPlugins()
415 { 415 {
416 m_plugineffects = new Dictionary<string, ITerrainEffect>(); 416 m_plugineffects = new Dictionary<string, ITerrainEffect>();
417 LoadPlugins(Assembly.GetCallingAssembly());
418 string plugineffectsPath = "Terrain"; 417 string plugineffectsPath = "Terrain";
419 418
420 // Load the files in the Terrain/ dir 419 // Load the files in the Terrain/ dir
@@ -428,39 +427,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain
428 try 427 try
429 { 428 {
430 Assembly library = Assembly.LoadFrom(file); 429 Assembly library = Assembly.LoadFrom(file);
431 LoadPlugins(library); 430 foreach (Type pluginType in library.GetTypes())
432 } 431 {
433 catch (BadImageFormatException) 432 try
434 { 433 {
435 } 434 if (pluginType.IsAbstract || pluginType.IsNotPublic)
436 } 435 continue;
437 }
438
439 private void LoadPlugins(Assembly library)
440 {
441 foreach (Type pluginType in library.GetTypes())
442 {
443 try
444 {
445 if (pluginType.IsAbstract || pluginType.IsNotPublic)
446 continue;
447 436
448 string typeName = pluginType.Name; 437 string typeName = pluginType.Name;
449 438
450 if (pluginType.GetInterface("ITerrainEffect", false) != null) 439 if (pluginType.GetInterface("ITerrainEffect", false) != null)
451 { 440 {
452 ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); 441 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
453 442
454 InstallPlugin(typeName, terEffect); 443 InstallPlugin(typeName, terEffect);
455 } 444 }
456 else if (pluginType.GetInterface("ITerrainLoader", false) != null) 445 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
457 { 446 {
458 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); 447 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
459 m_loaders[terLoader.FileExtension] = terLoader; 448 m_loaders[terLoader.FileExtension] = terLoader;
460 m_log.Info("L ... " + typeName); 449 m_log.Info("L ... " + typeName);
450 }
451 }
452 catch (AmbiguousMatchException)
453 {
454 }
461 } 455 }
462 } 456 }
463 catch (AmbiguousMatchException) 457 catch (BadImageFormatException)
464 { 458 {
465 } 459 }
466 } 460 }
@@ -1184,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1184 1178
1185 private void InterfaceRunPluginEffect(Object[] args) 1179 private void InterfaceRunPluginEffect(Object[] args)
1186 { 1180 {
1187 string firstArg = (string)args[0]; 1181 if ((string) args[0] == "list")
1188 if (firstArg == "list")
1189 { 1182 {
1190 m_log.Info("List of loaded plugins"); 1183 m_log.Info("List of loaded plugins");
1191 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1184 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@@ -1194,14 +1187,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1194 } 1187 }
1195 return; 1188 return;
1196 } 1189 }
1197 if (firstArg == "reload") 1190 if ((string) args[0] == "reload")
1198 { 1191 {
1199 LoadPlugins(); 1192 LoadPlugins();
1200 return; 1193 return;
1201 } 1194 }
1202 if (m_plugineffects.ContainsKey(firstArg)) 1195 if (m_plugineffects.ContainsKey((string) args[0]))
1203 { 1196 {
1204 m_plugineffects[firstArg].RunEffect(m_channel); 1197 m_plugineffects[(string) args[0]].RunEffect(m_channel);
1205 CheckForTerrainUpdates(); 1198 CheckForTerrainUpdates();
1206 } 1199 }
1207 else 1200 else
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 33f6c3f..3c48d07 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -222,13 +222,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); 222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 } 223 }
224 224
225 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
226 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
227 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
228 // this map tile simply takes a lot of memory.
229 GC.Collect();
230 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
231
232 return bitmap; 225 return bitmap;
233 } 226 }
234 227
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index dc54c3f..c5c96a9 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -130,25 +130,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
130 m_scriptModule.PostScriptEvent(script, "link_message", args); 130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 } 131 }
132 132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
146 public void RegisterScriptInvocation(object target, string meth) 133 public void RegisterScriptInvocation(object target, string meth)
147 { 134 {
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 135 MethodInfo mi = target.GetType().GetMethod(meth,
136 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
149 if (mi == null) 137 if (mi == null)
150 { 138 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 139 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth);
152 return; 140 return;
153 } 141 }
154 142
@@ -163,71 +151,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
163 151
164 public void RegisterScriptInvocation(object target, MethodInfo mi) 152 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 { 153 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 154 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name);
167 155
168 Type delegateType; 156 Type delegateType;
169 List<Type> typeArgs = mi.GetParameters() 157 var typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 158 .Select(p => p.ParameterType)
171 .ToList(); 159 .ToList();
172 160
173 if (mi.ReturnType == typeof(void)) 161 if (mi.ReturnType == typeof(void))
174 { 162 {
175 delegateType = Expression.GetActionType(typeArgs.ToArray()); 163 delegateType = Expression.GetActionType(typeArgs.ToArray());
176 } 164 }
177 else 165 else
178 { 166 {
179 typeArgs.Add(mi.ReturnType); 167 typeArgs.Add(mi.ReturnType);
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 168 delegateType = Expression.GetFuncType(typeArgs.ToArray());
181 } 169 }
182 170
183 Delegate fcall; 171 Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi);
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
188 172
189 lock (m_scriptInvocation) 173 lock (m_scriptInvocation)
190 { 174 {
191 ParameterInfo[] parameters = fcall.Method.GetParameters(); 175 ParameterInfo[] parameters = fcall.Method.GetParameters ();
192 if (parameters.Length < 2) // Must have two UUID params 176 if (parameters.Length < 2) // Must have two UUID params
193 return; 177 return;
194 178
195 // Hide the first two parameters 179 // Hide the first two parameters
196 Type[] parmTypes = new Type[parameters.Length - 2]; 180 Type[] parmTypes = new Type[parameters.Length - 2];
197 for (int i = 2; i < parameters.Length; i++) 181 for (int i = 2 ; i < parameters.Length ; i++)
198 parmTypes[i - 2] = parameters[i].ParameterType; 182 parmTypes[i - 2] = parameters[i].ParameterType;
199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); 183 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
200 } 184 }
201 } 185 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
214
215 public void RegisterScriptInvocations(IRegionModuleBase target)
216 {
217 foreach(MethodInfo method in target.GetType().GetMethods(
218 BindingFlags.Public | BindingFlags.Instance |
219 BindingFlags.Static))
220 {
221 if(method.GetCustomAttributes(
222 typeof(ScriptInvocationAttribute), true).Any())
223 {
224 if(method.IsStatic)
225 RegisterScriptInvocation(target.GetType(), method);
226 else
227 RegisterScriptInvocation(target, method);
228 }
229 }
230 }
231 186
232 public Delegate[] GetScriptInvocationList() 187 public Delegate[] GetScriptInvocationList()
233 { 188 {
@@ -330,20 +285,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
330 } 285 }
331 } 286 }
332 287
333 public void RegisterConstants(IRegionModuleBase target)
334 {
335 foreach (FieldInfo field in target.GetType().GetFields(
336 BindingFlags.Public | BindingFlags.Static |
337 BindingFlags.Instance))
338 {
339 if (field.GetCustomAttributes(
340 typeof(ScriptConstantAttribute), true).Any())
341 {
342 RegisterConstant(field.Name, field.GetValue(target));
343 }
344 }
345 }
346
347 /// <summary> 288 /// <summary>
348 /// Operation to check for a registered constant 289 /// Operation to check for a registered constant
349 /// </summary> 290 /// </summary>