aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-05-09 23:25:01 +0100
committerJustin Clark-Casey (justincc)2012-05-09 23:25:01 +0100
commitd8a78374aa11c5460d6e58a6f4110fca61dfded4 (patch)
tree4214094c092eeff11f2dcd60f71cfc294ab887be /OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
parentImprove logging on the prim inventory script asset request path for future use. (diff)
downloadopensim-SC_OLD-d8a78374aa11c5460d6e58a6f4110fca61dfded4.zip
opensim-SC_OLD-d8a78374aa11c5460d6e58a6f4110fca61dfded4.tar.gz
opensim-SC_OLD-d8a78374aa11c5460d6e58a6f4110fca61dfded4.tar.bz2
opensim-SC_OLD-d8a78374aa11c5460d6e58a6f4110fca61dfded4.tar.xz
Where necessary, rename OpenSim/Services/Connectors/*.cs files to reflect the actual class names.
This is usually because the file name was singular (*Service*) but the class name was plural (*Services*). This is to make configuration easier rather than having to look in the c# code itself to find the slightly different name of the connector. This does not affect existing configuration since the files are being renamed rather than the classes.
Diffstat (limited to 'OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs')
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs329
1 files changed, 329 insertions, 0 deletions
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
new file mode 100644
index 0000000..e4c3eaf
--- /dev/null
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -0,0 +1,329 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class AssetServicesConnector : IAssetService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = String.Empty;
49 private IImprovedAssetCache m_Cache = null;
50
51 private delegate void AssetRetrievedEx(AssetBase asset);
52
53 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
54 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded
55 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
56
57
58 public AssetServicesConnector()
59 {
60 }
61
62 public AssetServicesConnector(string serverURI)
63 {
64 m_ServerURI = serverURI.TrimEnd('/');
65 }
66
67 public AssetServicesConnector(IConfigSource source)
68 {
69 Initialise(source);
70 }
71
72 public virtual void Initialise(IConfigSource source)
73 {
74 IConfig assetConfig = source.Configs["AssetService"];
75 if (assetConfig == null)
76 {
77 m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini");
78 throw new Exception("Asset connector init error");
79 }
80
81 string serviceURI = assetConfig.GetString("AssetServerURI",
82 String.Empty);
83
84 if (serviceURI == String.Empty)
85 {
86 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService");
87 throw new Exception("Asset connector init error");
88 }
89
90 m_ServerURI = serviceURI;
91 }
92
93 protected void SetCache(IImprovedAssetCache cache)
94 {
95 m_Cache = cache;
96 }
97
98 public AssetBase Get(string id)
99 {
100// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Synchronous get request for {0}", id);
101
102 string uri = m_ServerURI + "/assets/" + id;
103
104 AssetBase asset = null;
105 if (m_Cache != null)
106 asset = m_Cache.Get(id);
107
108 if (asset == null)
109 {
110 asset = SynchronousRestObjectRequester.
111 MakeRequest<int, AssetBase>("GET", uri, 0);
112
113 if (m_Cache != null)
114 m_Cache.Cache(asset);
115 }
116 return asset;
117 }
118
119 public AssetBase GetCached(string id)
120 {
121// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Cache request for {0}", id);
122
123 if (m_Cache != null)
124 return m_Cache.Get(id);
125
126 return null;
127 }
128
129 public AssetMetadata GetMetadata(string id)
130 {
131 if (m_Cache != null)
132 {
133 AssetBase fullAsset = m_Cache.Get(id);
134
135 if (fullAsset != null)
136 return fullAsset.Metadata;
137 }
138
139 string uri = m_ServerURI + "/assets/" + id + "/metadata";
140
141 AssetMetadata asset = SynchronousRestObjectRequester.
142 MakeRequest<int, AssetMetadata>("GET", uri, 0);
143 return asset;
144 }
145
146 public byte[] GetData(string id)
147 {
148 if (m_Cache != null)
149 {
150 AssetBase fullAsset = m_Cache.Get(id);
151
152 if (fullAsset != null)
153 return fullAsset.Data;
154 }
155
156 RestClient rc = new RestClient(m_ServerURI);
157 rc.AddResourcePath("assets");
158 rc.AddResourcePath(id);
159 rc.AddResourcePath("data");
160
161 rc.RequestMethod = "GET";
162
163 Stream s = rc.Request();
164
165 if (s == null)
166 return null;
167
168 if (s.Length > 0)
169 {
170 byte[] ret = new byte[s.Length];
171 s.Read(ret, 0, (int)s.Length);
172
173 return ret;
174 }
175
176 return null;
177 }
178
179 public bool Get(string id, Object sender, AssetRetrieved handler)
180 {
181// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Potentially asynchronous get request for {0}", id);
182
183 string uri = m_ServerURI + "/assets/" + id;
184
185 AssetBase asset = null;
186 if (m_Cache != null)
187 asset = m_Cache.Get(id);
188
189 if (asset == null)
190 {
191 lock (m_AssetHandlers)
192 {
193 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
194
195 AssetRetrievedEx handlers;
196 if (m_AssetHandlers.TryGetValue(id, out handlers))
197 {
198 // Someone else is already loading this asset. It will notify our handler when done.
199 handlers += handlerEx;
200 return true;
201 }
202
203 // Load the asset ourselves
204 handlers += handlerEx;
205 m_AssetHandlers.Add(id, handlers);
206 }
207
208 bool success = false;
209 try
210 {
211 AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
212 delegate(AssetBase a)
213 {
214 if (m_Cache != null)
215 m_Cache.Cache(a);
216
217 AssetRetrievedEx handlers;
218 lock (m_AssetHandlers)
219 {
220 handlers = m_AssetHandlers[id];
221 m_AssetHandlers.Remove(id);
222 }
223 handlers.Invoke(a);
224 });
225
226 success = true;
227 }
228 finally
229 {
230 if (!success)
231 {
232 lock (m_AssetHandlers)
233 {
234 m_AssetHandlers.Remove(id);
235 }
236 }
237 }
238 }
239 else
240 {
241 handler(id, sender, asset);
242 }
243
244 return true;
245 }
246
247 public string Store(AssetBase asset)
248 {
249 if (asset.Temporary || asset.Local)
250 {
251 if (m_Cache != null)
252 m_Cache.Cache(asset);
253
254 return asset.ID;
255 }
256
257 string uri = m_ServerURI + "/assets/";
258
259 string newID = string.Empty;
260 try
261 {
262 newID = SynchronousRestObjectRequester.
263 MakeRequest<AssetBase, string>("POST", uri, asset);
264 }
265 catch (Exception e)
266 {
267 m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message);
268 }
269
270 if (newID != String.Empty)
271 {
272 // Placing this here, so that this work with old asset servers that don't send any reply back
273 // SynchronousRestObjectRequester returns somethins that is not an empty string
274 if (newID != null)
275 asset.ID = newID;
276
277 if (m_Cache != null)
278 m_Cache.Cache(asset);
279 }
280 return newID;
281 }
282
283 public bool UpdateContent(string id, byte[] data)
284 {
285 AssetBase asset = null;
286
287 if (m_Cache != null)
288 asset = m_Cache.Get(id);
289
290 if (asset == null)
291 {
292 AssetMetadata metadata = GetMetadata(id);
293 if (metadata == null)
294 return false;
295
296 asset = new AssetBase(metadata.FullID, metadata.Name, metadata.Type, UUID.Zero.ToString());
297 asset.Metadata = metadata;
298 }
299 asset.Data = data;
300
301 string uri = m_ServerURI + "/assets/" + id;
302
303 if (SynchronousRestObjectRequester.
304 MakeRequest<AssetBase, bool>("POST", uri, asset))
305 {
306 if (m_Cache != null)
307 m_Cache.Cache(asset);
308
309 return true;
310 }
311 return false;
312 }
313
314 public bool Delete(string id)
315 {
316 string uri = m_ServerURI + "/assets/" + id;
317
318 if (SynchronousRestObjectRequester.
319 MakeRequest<int, bool>("DELETE", uri, 0))
320 {
321 if (m_Cache != null)
322 m_Cache.Expire(id);
323
324 return true;
325 }
326 return false;
327 }
328 }
329} \ No newline at end of file