diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs | 118 | ||||
-rw-r--r-- | OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs | 104 |
2 files changed, 144 insertions, 78 deletions
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 2b2f11f..bd43552 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs | |||
@@ -33,13 +33,12 @@ using System.Reflection; | |||
33 | using Nini.Config; | 33 | using Nini.Config; |
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Framework.Console; | 35 | using OpenSim.Framework.Console; |
36 | using OpenSim.Framework.Communications; | ||
37 | using OpenSim.Services.Interfaces; | 36 | using OpenSim.Services.Interfaces; |
38 | using OpenMetaverse; | 37 | using OpenMetaverse; |
39 | 38 | ||
40 | namespace OpenSim.Services.Connectors | 39 | namespace OpenSim.Services.Connectors |
41 | { | 40 | { |
42 | public class AssetServicesConnector : IAssetService | 41 | public class AssetServicesConnector : BaseServiceConnector, IAssetService |
43 | { | 42 | { |
44 | private static readonly ILog m_log = | 43 | private static readonly ILog m_log = |
45 | LogManager.GetLogger( | 44 | LogManager.GetLogger( |
@@ -55,6 +54,11 @@ namespace OpenSim.Services.Connectors | |||
55 | // Maps: Asset ID -> Handlers which will be called when the asset has been loaded | 54 | // Maps: Asset ID -> Handlers which will be called when the asset has been loaded |
56 | private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>(); | 55 | private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>(); |
57 | 56 | ||
57 | public int MaxAssetRequestConcurrency | ||
58 | { | ||
59 | get { return m_maxAssetRequestConcurrency; } | ||
60 | set { m_maxAssetRequestConcurrency = value; } | ||
61 | } | ||
58 | 62 | ||
59 | public AssetServicesConnector() | 63 | public AssetServicesConnector() |
60 | { | 64 | { |
@@ -66,6 +70,7 @@ namespace OpenSim.Services.Connectors | |||
66 | } | 70 | } |
67 | 71 | ||
68 | public AssetServicesConnector(IConfigSource source) | 72 | public AssetServicesConnector(IConfigSource source) |
73 | : base(source, "AssetService") | ||
69 | { | 74 | { |
70 | Initialise(source); | 75 | Initialise(source); |
71 | } | 76 | } |
@@ -112,8 +117,16 @@ namespace OpenSim.Services.Connectors | |||
112 | 117 | ||
113 | if (asset == null) | 118 | if (asset == null) |
114 | { | 119 | { |
115 | asset = SynchronousRestObjectRequester. | 120 | // XXX: Commented out for now since this has either never been properly operational or not for some time |
116 | MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency); | 121 | // as m_maxAssetRequestConcurrency was being passed as the timeout, not a concurrency limiting option. |
122 | // Wasn't noticed before because timeout wasn't actually used. | ||
123 | // Not attempting concurrency setting for now as this omission was discovered in release candidate | ||
124 | // phase for OpenSimulator 0.8. Need to revisit afterwards. | ||
125 | // asset | ||
126 | // = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>( | ||
127 | // "GET", uri, 0, m_maxAssetRequestConcurrency); | ||
128 | |||
129 | asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth); | ||
117 | 130 | ||
118 | if (m_Cache != null) | 131 | if (m_Cache != null) |
119 | m_Cache.Cache(asset); | 132 | m_Cache.Cache(asset); |
@@ -143,8 +156,7 @@ namespace OpenSim.Services.Connectors | |||
143 | 156 | ||
144 | string uri = m_ServerURI + "/assets/" + id + "/metadata"; | 157 | string uri = m_ServerURI + "/assets/" + id + "/metadata"; |
145 | 158 | ||
146 | AssetMetadata asset = SynchronousRestObjectRequester. | 159 | AssetMetadata asset = SynchronousRestObjectRequester.MakeRequest<int, AssetMetadata>("GET", uri, 0, m_Auth); |
147 | MakeRequest<int, AssetMetadata>("GET", uri, 0); | ||
148 | return asset; | 160 | return asset; |
149 | } | 161 | } |
150 | 162 | ||
@@ -158,27 +170,29 @@ namespace OpenSim.Services.Connectors | |||
158 | return fullAsset.Data; | 170 | return fullAsset.Data; |
159 | } | 171 | } |
160 | 172 | ||
161 | RestClient rc = new RestClient(m_ServerURI); | 173 | using (RestClient rc = new RestClient(m_ServerURI)) |
162 | rc.AddResourcePath("assets"); | 174 | { |
163 | rc.AddResourcePath(id); | 175 | rc.AddResourcePath("assets"); |
164 | rc.AddResourcePath("data"); | 176 | rc.AddResourcePath(id); |
177 | rc.AddResourcePath("data"); | ||
165 | 178 | ||
166 | rc.RequestMethod = "GET"; | 179 | rc.RequestMethod = "GET"; |
167 | 180 | ||
168 | Stream s = rc.Request(); | 181 | Stream s = rc.Request(m_Auth); |
169 | 182 | ||
170 | if (s == null) | 183 | if (s == null) |
171 | return null; | 184 | return null; |
172 | 185 | ||
173 | if (s.Length > 0) | 186 | if (s.Length > 0) |
174 | { | 187 | { |
175 | byte[] ret = new byte[s.Length]; | 188 | byte[] ret = new byte[s.Length]; |
176 | s.Read(ret, 0, (int)s.Length); | 189 | s.Read(ret, 0, (int)s.Length); |
177 | 190 | ||
178 | return ret; | 191 | return ret; |
179 | } | 192 | } |
180 | 193 | ||
181 | return null; | 194 | return null; |
195 | } | ||
182 | } | 196 | } |
183 | 197 | ||
184 | public bool Get(string id, Object sender, AssetRetrieved handler) | 198 | public bool Get(string id, Object sender, AssetRetrieved handler) |
@@ -216,7 +230,7 @@ namespace OpenSim.Services.Connectors | |||
216 | AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, | 230 | AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, |
217 | delegate(AssetBase a) | 231 | delegate(AssetBase a) |
218 | { | 232 | { |
219 | if (m_Cache != null) | 233 | if (a != null && m_Cache != null) |
220 | m_Cache.Cache(a); | 234 | m_Cache.Cache(a); |
221 | 235 | ||
222 | AssetRetrievedEx handlers; | 236 | AssetRetrievedEx handlers; |
@@ -226,7 +240,7 @@ namespace OpenSim.Services.Connectors | |||
226 | m_AssetHandlers.Remove(id); | 240 | m_AssetHandlers.Remove(id); |
227 | } | 241 | } |
228 | handlers.Invoke(a); | 242 | handlers.Invoke(a); |
229 | }, m_maxAssetRequestConcurrency); | 243 | }, m_maxAssetRequestConcurrency, m_Auth); |
230 | 244 | ||
231 | success = true; | 245 | success = true; |
232 | } | 246 | } |
@@ -249,9 +263,30 @@ namespace OpenSim.Services.Connectors | |||
249 | return true; | 263 | return true; |
250 | } | 264 | } |
251 | 265 | ||
266 | public virtual bool[] AssetsExist(string[] ids) | ||
267 | { | ||
268 | string uri = m_ServerURI + "/get_assets_exist"; | ||
269 | |||
270 | bool[] exist = null; | ||
271 | try | ||
272 | { | ||
273 | exist = SynchronousRestObjectRequester.MakeRequest<string[], bool[]>("POST", uri, ids, m_Auth); | ||
274 | } | ||
275 | catch (Exception) | ||
276 | { | ||
277 | // This is most likely to happen because the server doesn't support this function, | ||
278 | // so just silently return "doesn't exist" for all the assets. | ||
279 | } | ||
280 | |||
281 | if (exist == null) | ||
282 | exist = new bool[ids.Length]; | ||
283 | |||
284 | return exist; | ||
285 | } | ||
286 | |||
252 | public string Store(AssetBase asset) | 287 | public string Store(AssetBase asset) |
253 | { | 288 | { |
254 | if (asset.Temporary || asset.Local) | 289 | if (asset.Local) |
255 | { | 290 | { |
256 | if (m_Cache != null) | 291 | if (m_Cache != null) |
257 | m_Cache.Cache(asset); | 292 | m_Cache.Cache(asset); |
@@ -261,27 +296,32 @@ namespace OpenSim.Services.Connectors | |||
261 | 296 | ||
262 | string uri = m_ServerURI + "/assets/"; | 297 | string uri = m_ServerURI + "/assets/"; |
263 | 298 | ||
264 | string newID = string.Empty; | 299 | string newID; |
265 | try | 300 | try |
266 | { | 301 | { |
267 | newID = SynchronousRestObjectRequester. | 302 | newID = SynchronousRestObjectRequester.MakeRequest<AssetBase, string>("POST", uri, asset, m_Auth); |
268 | MakeRequest<AssetBase, string>("POST", uri, asset); | ||
269 | } | 303 | } |
270 | catch (Exception e) | 304 | catch (Exception e) |
271 | { | 305 | { |
272 | m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message); | 306 | m_log.Warn(string.Format("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1} ", asset.ID, e.Message), e); |
307 | return string.Empty; | ||
273 | } | 308 | } |
274 | 309 | ||
275 | if (newID != String.Empty) | 310 | // TEMPORARY: SRAS returns 'null' when it's asked to store existing assets |
311 | if (newID == null) | ||
276 | { | 312 | { |
277 | // Placing this here, so that this work with old asset servers that don't send any reply back | 313 | m_log.DebugFormat("[ASSET CONNECTOR]: Storing of asset {0} returned null; assuming the asset already exists", asset.ID); |
278 | // SynchronousRestObjectRequester returns somethins that is not an empty string | 314 | return asset.ID; |
279 | if (newID != null) | ||
280 | asset.ID = newID; | ||
281 | |||
282 | if (m_Cache != null) | ||
283 | m_Cache.Cache(asset); | ||
284 | } | 315 | } |
316 | |||
317 | if (string.IsNullOrEmpty(newID)) | ||
318 | return string.Empty; | ||
319 | |||
320 | asset.ID = newID; | ||
321 | |||
322 | if (m_Cache != null) | ||
323 | m_Cache.Cache(asset); | ||
324 | |||
285 | return newID; | 325 | return newID; |
286 | } | 326 | } |
287 | 327 | ||
@@ -305,8 +345,7 @@ namespace OpenSim.Services.Connectors | |||
305 | 345 | ||
306 | string uri = m_ServerURI + "/assets/" + id; | 346 | string uri = m_ServerURI + "/assets/" + id; |
307 | 347 | ||
308 | if (SynchronousRestObjectRequester. | 348 | if (SynchronousRestObjectRequester.MakeRequest<AssetBase, bool>("POST", uri, asset, m_Auth)) |
309 | MakeRequest<AssetBase, bool>("POST", uri, asset)) | ||
310 | { | 349 | { |
311 | if (m_Cache != null) | 350 | if (m_Cache != null) |
312 | m_Cache.Cache(asset); | 351 | m_Cache.Cache(asset); |
@@ -320,8 +359,7 @@ namespace OpenSim.Services.Connectors | |||
320 | { | 359 | { |
321 | string uri = m_ServerURI + "/assets/" + id; | 360 | string uri = m_ServerURI + "/assets/" + id; |
322 | 361 | ||
323 | if (SynchronousRestObjectRequester. | 362 | if (SynchronousRestObjectRequester.MakeRequest<int, bool>("DELETE", uri, 0, m_Auth)) |
324 | MakeRequest<int, bool>("DELETE", uri, 0)) | ||
325 | { | 363 | { |
326 | if (m_Cache != null) | 364 | if (m_Cache != null) |
327 | m_Cache.Expire(id); | 365 | m_Cache.Expire(id); |
diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index c395178..3710c86 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs | |||
@@ -36,6 +36,7 @@ using OpenSim.Framework; | |||
36 | using OpenSim.Services.Interfaces; | 36 | using OpenSim.Services.Interfaces; |
37 | using OpenSim.Services.Connectors.Hypergrid; | 37 | using OpenSim.Services.Connectors.Hypergrid; |
38 | using OpenSim.Services.Connectors.SimianGrid; | 38 | using OpenSim.Services.Connectors.SimianGrid; |
39 | using OpenMetaverse; | ||
39 | 40 | ||
40 | namespace OpenSim.Services.Connectors | 41 | namespace OpenSim.Services.Connectors |
41 | { | 42 | { |
@@ -83,39 +84,6 @@ namespace OpenSim.Services.Connectors | |||
83 | } | 84 | } |
84 | } | 85 | } |
85 | 86 | ||
86 | private bool StringToUrlAndAssetID(string id, out string url, out string assetID) | ||
87 | { | ||
88 | url = String.Empty; | ||
89 | assetID = String.Empty; | ||
90 | |||
91 | Uri assetUri; | ||
92 | |||
93 | if (Uri.TryCreate(id, UriKind.Absolute, out assetUri) && | ||
94 | assetUri.Scheme == Uri.UriSchemeHttp) | ||
95 | { | ||
96 | // Simian | ||
97 | if (assetUri.Query != string.Empty) | ||
98 | { | ||
99 | NameValueCollection qscoll = HttpUtility.ParseQueryString(assetUri.Query); | ||
100 | assetID = qscoll["id"]; | ||
101 | if (assetID != null) | ||
102 | url = id.Replace(assetID, ""); // Malformed again, as simian expects | ||
103 | else | ||
104 | url = id; // !!! best effort | ||
105 | } | ||
106 | else // robust | ||
107 | { | ||
108 | url = "http://" + assetUri.Authority; | ||
109 | assetID = assetUri.LocalPath.Trim(new char[] { '/' }); | ||
110 | } | ||
111 | |||
112 | return true; | ||
113 | } | ||
114 | |||
115 | m_log.DebugFormat("[HG ASSET SERVICE]: Malformed URL {0}", id); | ||
116 | return false; | ||
117 | } | ||
118 | |||
119 | private IAssetService GetConnector(string url) | 87 | private IAssetService GetConnector(string url) |
120 | { | 88 | { |
121 | IAssetService connector = null; | 89 | IAssetService connector = null; |
@@ -149,7 +117,7 @@ namespace OpenSim.Services.Connectors | |||
149 | string url = string.Empty; | 117 | string url = string.Empty; |
150 | string assetID = string.Empty; | 118 | string assetID = string.Empty; |
151 | 119 | ||
152 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 120 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
153 | { | 121 | { |
154 | IAssetService connector = GetConnector(url); | 122 | IAssetService connector = GetConnector(url); |
155 | return connector.Get(assetID); | 123 | return connector.Get(assetID); |
@@ -163,7 +131,7 @@ namespace OpenSim.Services.Connectors | |||
163 | string url = string.Empty; | 131 | string url = string.Empty; |
164 | string assetID = string.Empty; | 132 | string assetID = string.Empty; |
165 | 133 | ||
166 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 134 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
167 | { | 135 | { |
168 | IAssetService connector = GetConnector(url); | 136 | IAssetService connector = GetConnector(url); |
169 | return connector.GetCached(assetID); | 137 | return connector.GetCached(assetID); |
@@ -177,7 +145,7 @@ namespace OpenSim.Services.Connectors | |||
177 | string url = string.Empty; | 145 | string url = string.Empty; |
178 | string assetID = string.Empty; | 146 | string assetID = string.Empty; |
179 | 147 | ||
180 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 148 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
181 | { | 149 | { |
182 | IAssetService connector = GetConnector(url); | 150 | IAssetService connector = GetConnector(url); |
183 | return connector.GetMetadata(assetID); | 151 | return connector.GetMetadata(assetID); |
@@ -196,7 +164,7 @@ namespace OpenSim.Services.Connectors | |||
196 | string url = string.Empty; | 164 | string url = string.Empty; |
197 | string assetID = string.Empty; | 165 | string assetID = string.Empty; |
198 | 166 | ||
199 | if (StringToUrlAndAssetID(id, out url, out assetID)) | 167 | if (Util.ParseForeignAssetID(id, out url, out assetID)) |
200 | { | 168 | { |
201 | IAssetService connector = GetConnector(url); | 169 | IAssetService connector = GetConnector(url); |
202 | return connector.Get(assetID, sender, handler); | 170 | return connector.Get(assetID, sender, handler); |
@@ -205,12 +173,72 @@ namespace OpenSim.Services.Connectors | |||
205 | return false; | 173 | return false; |
206 | } | 174 | } |
207 | 175 | ||
176 | |||
177 | private struct AssetAndIndex | ||
178 | { | ||
179 | public UUID assetID; | ||
180 | public int index; | ||
181 | |||
182 | public AssetAndIndex(UUID assetID, int index) | ||
183 | { | ||
184 | this.assetID = assetID; | ||
185 | this.index = index; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | public virtual bool[] AssetsExist(string[] ids) | ||
190 | { | ||
191 | // This method is a bit complicated because it works even if the assets belong to different | ||
192 | // servers; that requires sending separate requests to each server. | ||
193 | |||
194 | // Group the assets by the server they belong to | ||
195 | |||
196 | var url2assets = new Dictionary<string, List<AssetAndIndex>>(); | ||
197 | |||
198 | for (int i = 0; i < ids.Length; i++) | ||
199 | { | ||
200 | string url = string.Empty; | ||
201 | string assetID = string.Empty; | ||
202 | |||
203 | if (Util.ParseForeignAssetID(ids[i], out url, out assetID)) | ||
204 | { | ||
205 | if (!url2assets.ContainsKey(url)) | ||
206 | url2assets.Add(url, new List<AssetAndIndex>()); | ||
207 | url2assets[url].Add(new AssetAndIndex(UUID.Parse(assetID), i)); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | // Query each of the servers in turn | ||
212 | |||
213 | bool[] exist = new bool[ids.Length]; | ||
214 | |||
215 | foreach (string url in url2assets.Keys) | ||
216 | { | ||
217 | IAssetService connector = GetConnector(url); | ||
218 | lock (EndPointLock(connector)) | ||
219 | { | ||
220 | List<AssetAndIndex> curAssets = url2assets[url]; | ||
221 | string[] assetIDs = curAssets.ConvertAll(a => a.assetID.ToString()).ToArray(); | ||
222 | bool[] curExist = connector.AssetsExist(assetIDs); | ||
223 | |||
224 | int i = 0; | ||
225 | foreach (AssetAndIndex ai in curAssets) | ||
226 | { | ||
227 | exist[ai.index] = curExist[i]; | ||
228 | ++i; | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | |||
233 | return exist; | ||
234 | } | ||
235 | |||
208 | public string Store(AssetBase asset) | 236 | public string Store(AssetBase asset) |
209 | { | 237 | { |
210 | string url = string.Empty; | 238 | string url = string.Empty; |
211 | string assetID = string.Empty; | 239 | string assetID = string.Empty; |
212 | 240 | ||
213 | if (StringToUrlAndAssetID(asset.ID, out url, out assetID)) | 241 | if (Util.ParseForeignAssetID(asset.ID, out url, out assetID)) |
214 | { | 242 | { |
215 | IAssetService connector = GetConnector(url); | 243 | IAssetService connector = GetConnector(url); |
216 | // Restore the assetID to a simple UUID | 244 | // Restore the assetID to a simple UUID |