diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Services/FSAssetService/FSAssetService.cs | 199 |
1 files changed, 146 insertions, 53 deletions
diff --git a/OpenSim/Services/FSAssetService/FSAssetService.cs b/OpenSim/Services/FSAssetService/FSAssetService.cs index aba8b33..ca2f459 100644 --- a/OpenSim/Services/FSAssetService/FSAssetService.cs +++ b/OpenSim/Services/FSAssetService/FSAssetService.cs | |||
@@ -76,6 +76,8 @@ namespace OpenSim.Services.FSAssetService | |||
76 | protected int m_missingAssets = 0; | 76 | protected int m_missingAssets = 0; |
77 | protected int m_missingAssetsFS = 0; | 77 | protected int m_missingAssetsFS = 0; |
78 | protected string m_FSBase; | 78 | protected string m_FSBase; |
79 | protected bool m_useOsgridFormat = false; | ||
80 | protected bool m_showStats = true; | ||
79 | 81 | ||
80 | private static bool m_Initialized; | 82 | private static bool m_Initialized; |
81 | private bool m_MainInstance; | 83 | private bool m_MainInstance; |
@@ -113,34 +115,34 @@ namespace OpenSim.Services.FSAssetService | |||
113 | } | 115 | } |
114 | 116 | ||
115 | IConfig assetConfig = config.Configs[configName]; | 117 | IConfig assetConfig = config.Configs[configName]; |
116 | 118 | ||
117 | if (assetConfig == null) | 119 | if (assetConfig == null) |
118 | throw new Exception("No AssetService configuration"); | 120 | throw new Exception("No AssetService configuration"); |
119 | 121 | ||
120 | // Get Database Connector from Asset Config (If present) | 122 | // Get Database Connector from Asset Config (If present) |
121 | string dllName = assetConfig.GetString("StorageProvider", string.Empty); | 123 | string dllName = assetConfig.GetString("StorageProvider", string.Empty); |
122 | string m_ConnectionString = assetConfig.GetString("ConnectionString", string.Empty); | 124 | string connectionString = assetConfig.GetString("ConnectionString", string.Empty); |
123 | string m_Realm = assetConfig.GetString("Realm", "fsassets"); | 125 | string realm = assetConfig.GetString("Realm", "fsassets"); |
124 | 126 | ||
125 | int SkipAccessTimeDays = assetConfig.GetInt("DaysBetweenAccessTimeUpdates", 0); | 127 | int SkipAccessTimeDays = assetConfig.GetInt("DaysBetweenAccessTimeUpdates", 0); |
126 | 128 | ||
127 | // If not found above, fallback to Database defaults | 129 | // If not found above, fallback to Database defaults |
128 | IConfig dbConfig = config.Configs["DatabaseService"]; | 130 | IConfig dbConfig = config.Configs["DatabaseService"]; |
129 | 131 | ||
130 | if (dbConfig != null) | 132 | if (dbConfig != null) |
131 | { | 133 | { |
132 | if (dllName == String.Empty) | 134 | if (dllName == String.Empty) |
133 | dllName = dbConfig.GetString("StorageProvider", String.Empty); | 135 | dllName = dbConfig.GetString("StorageProvider", String.Empty); |
134 | 136 | ||
135 | if (m_ConnectionString == String.Empty) | 137 | if (connectionString == String.Empty) |
136 | m_ConnectionString = dbConfig.GetString("ConnectionString", String.Empty); | 138 | connectionString = dbConfig.GetString("ConnectionString", String.Empty); |
137 | } | 139 | } |
138 | 140 | ||
139 | // No databse connection found in either config | 141 | // No databse connection found in either config |
140 | if (dllName.Equals(String.Empty)) | 142 | if (dllName.Equals(String.Empty)) |
141 | throw new Exception("No StorageProvider configured"); | 143 | throw new Exception("No StorageProvider configured"); |
142 | 144 | ||
143 | if (m_ConnectionString.Equals(String.Empty)) | 145 | if (connectionString.Equals(String.Empty)) |
144 | throw new Exception("Missing database connection string"); | 146 | throw new Exception("Missing database connection string"); |
145 | 147 | ||
146 | // Create Storage Provider | 148 | // Create Storage Provider |
@@ -150,11 +152,11 @@ namespace OpenSim.Services.FSAssetService | |||
150 | throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); | 152 | throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); |
151 | 153 | ||
152 | // Initialize DB And perform any migrations required | 154 | // Initialize DB And perform any migrations required |
153 | m_DataConnector.Initialise(m_ConnectionString, m_Realm, SkipAccessTimeDays); | 155 | m_DataConnector.Initialise(connectionString, realm, SkipAccessTimeDays); |
154 | 156 | ||
155 | // Setup Fallback Service | 157 | // Setup Fallback Service |
156 | string str = assetConfig.GetString("FallbackService", string.Empty); | 158 | string str = assetConfig.GetString("FallbackService", string.Empty); |
157 | 159 | ||
158 | if (str != string.Empty) | 160 | if (str != string.Empty) |
159 | { | 161 | { |
160 | object[] args = new object[] { config }; | 162 | object[] args = new object[] { config }; |
@@ -183,6 +185,11 @@ namespace OpenSim.Services.FSAssetService | |||
183 | throw new Exception("Configuration error"); | 185 | throw new Exception("Configuration error"); |
184 | } | 186 | } |
185 | 187 | ||
188 | m_useOsgridFormat = assetConfig.GetBoolean("UseOsgridFormat", m_useOsgridFormat); | ||
189 | |||
190 | // Default is to show stats to retain original behaviour | ||
191 | m_showStats = assetConfig.GetBoolean("ShowConsoleStats", m_showStats); | ||
192 | |||
186 | if (m_MainInstance) | 193 | if (m_MainInstance) |
187 | { | 194 | { |
188 | string loader = assetConfig.GetString("DefaultAssetLoader", string.Empty); | 195 | string loader = assetConfig.GetString("DefaultAssetLoader", string.Empty); |
@@ -197,13 +204,17 @@ namespace OpenSim.Services.FSAssetService | |||
197 | Store(a, false); | 204 | Store(a, false); |
198 | }); | 205 | }); |
199 | } | 206 | } |
200 | 207 | ||
201 | m_WriterThread = new Thread(Writer); | 208 | m_WriterThread = new Thread(Writer); |
202 | m_WriterThread.Start(); | 209 | m_WriterThread.Start(); |
203 | m_StatsThread = new Thread(Stats); | 210 | |
204 | m_StatsThread.Start(); | 211 | if (m_showStats) |
212 | { | ||
213 | m_StatsThread = new Thread(Stats); | ||
214 | m_StatsThread.Start(); | ||
215 | } | ||
205 | } | 216 | } |
206 | 217 | ||
207 | m_log.Info("[FSASSETS]: FS asset service enabled"); | 218 | m_log.Info("[FSASSETS]: FS asset service enabled"); |
208 | } | 219 | } |
209 | 220 | ||
@@ -212,7 +223,7 @@ namespace OpenSim.Services.FSAssetService | |||
212 | while (true) | 223 | while (true) |
213 | { | 224 | { |
214 | Thread.Sleep(60000); | 225 | Thread.Sleep(60000); |
215 | 226 | ||
216 | lock (m_statsLock) | 227 | lock (m_statsLock) |
217 | { | 228 | { |
218 | if (m_readCount > 0) | 229 | if (m_readCount > 0) |
@@ -220,6 +231,7 @@ namespace OpenSim.Services.FSAssetService | |||
220 | double avg = (double)m_readTicks / (double)m_readCount; | 231 | double avg = (double)m_readTicks / (double)m_readCount; |
221 | // if (avg > 10000) | 232 | // if (avg > 10000) |
222 | // Environment.Exit(0); | 233 | // Environment.Exit(0); |
234 | m_log.InfoFormat("[FSASSETS]: Read stats: {0} files, {1} ticks, avg {2:F2}, missing {3}, FS {4}", m_readCount, m_readTicks, (double)m_readTicks / (double)m_readCount, m_missingAssets, m_missingAssetsFS); | ||
223 | } | 235 | } |
224 | m_readCount = 0; | 236 | m_readCount = 0; |
225 | m_readTicks = 0; | 237 | m_readTicks = 0; |
@@ -231,7 +243,7 @@ namespace OpenSim.Services.FSAssetService | |||
231 | 243 | ||
232 | private void Writer() | 244 | private void Writer() |
233 | { | 245 | { |
234 | m_log.Info("[FSASSETS]: Writer started"); | 246 | m_log.Info("[ASSET]: Writer started"); |
235 | 247 | ||
236 | while (true) | 248 | while (true) |
237 | { | 249 | { |
@@ -245,33 +257,98 @@ namespace OpenSim.Services.FSAssetService | |||
245 | string hash = Path.GetFileNameWithoutExtension(files[i]); | 257 | string hash = Path.GetFileNameWithoutExtension(files[i]); |
246 | string s = HashToFile(hash); | 258 | string s = HashToFile(hash); |
247 | string diskFile = Path.Combine(m_FSBase, s); | 259 | string diskFile = Path.Combine(m_FSBase, s); |
260 | bool pathOk = false; | ||
248 | 261 | ||
249 | Directory.CreateDirectory(Path.GetDirectoryName(diskFile)); | 262 | // The cure for chicken bones! |
250 | try | 263 | while(true) |
251 | { | 264 | { |
252 | byte[] data = File.ReadAllBytes(files[i]); | 265 | try |
253 | |||
254 | using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Create), CompressionMode.Compress)) | ||
255 | { | 266 | { |
256 | gz.Write(data, 0, data.Length); | 267 | // Try to make the directory we need for this file |
257 | gz.Close(); | 268 | Directory.CreateDirectory(Path.GetDirectoryName(diskFile)); |
269 | pathOk = true; | ||
270 | break; | ||
258 | } | 271 | } |
259 | File.Delete(files[i]); | 272 | catch (System.IO.IOException) |
260 | 273 | { | |
261 | //File.Move(files[i], diskFile); | 274 | // Creating the directory failed. This can't happen unless |
275 | // a part of the path already exists as a file. Sadly the | ||
276 | // SRAS data contains such files. | ||
277 | string d = Path.GetDirectoryName(diskFile); | ||
278 | |||
279 | // Test each path component in turn. If we can successfully | ||
280 | // make a directory, the level below must be the chicken bone. | ||
281 | while (d.Length > 0) | ||
282 | { | ||
283 | Console.WriteLine(d); | ||
284 | try | ||
285 | { | ||
286 | Directory.CreateDirectory(Path.GetDirectoryName(d)); | ||
287 | } | ||
288 | catch (System.IO.IOException) | ||
289 | { | ||
290 | d = Path.GetDirectoryName(d); | ||
291 | |||
292 | // We failed making the directory and need to | ||
293 | // go up a bit more | ||
294 | continue; | ||
295 | } | ||
296 | |||
297 | // We succeeded in making the directory and (d) is | ||
298 | // the chicken bone | ||
299 | break; | ||
300 | } | ||
301 | |||
302 | // Is the chicken alive? | ||
303 | if (d.Length > 0) | ||
304 | { | ||
305 | Console.WriteLine(d); | ||
306 | |||
307 | FileAttributes attr = File.GetAttributes(d); | ||
308 | |||
309 | if ((attr & FileAttributes.Directory) == 0) | ||
310 | { | ||
311 | // The chicken bone should be resolved. | ||
312 | // Return to writing the file. | ||
313 | File.Delete(d); | ||
314 | continue; | ||
315 | } | ||
316 | } | ||
317 | } | ||
318 | // Could not resolve, skipping | ||
319 | m_log.ErrorFormat("[ASSET]: Could not resolve path creation error for {0}", diskFile); | ||
320 | break; | ||
262 | } | 321 | } |
263 | catch(System.IO.IOException e) | 322 | |
323 | if (pathOk) | ||
264 | { | 324 | { |
265 | if (e.Message.StartsWith("Win32 IO returned ERROR_ALREADY_EXISTS")) | 325 | try |
326 | { | ||
327 | byte[] data = File.ReadAllBytes(files[i]); | ||
328 | |||
329 | using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Create), CompressionMode.Compress)) | ||
330 | { | ||
331 | gz.Write(data, 0, data.Length); | ||
332 | gz.Close(); | ||
333 | } | ||
266 | File.Delete(files[i]); | 334 | File.Delete(files[i]); |
267 | else | 335 | |
268 | throw; | 336 | //File.Move(files[i], diskFile); |
337 | } | ||
338 | catch(System.IO.IOException e) | ||
339 | { | ||
340 | if (e.Message.StartsWith("Win32 IO returned ERROR_ALREADY_EXISTS")) | ||
341 | File.Delete(files[i]); | ||
342 | else | ||
343 | throw; | ||
344 | } | ||
269 | } | 345 | } |
270 | } | 346 | } |
347 | |||
271 | int totalTicks = System.Environment.TickCount - tickCount; | 348 | int totalTicks = System.Environment.TickCount - tickCount; |
272 | if (totalTicks > 0) // Wrap? | 349 | if (totalTicks > 0) // Wrap? |
273 | { | 350 | { |
274 | m_log.InfoFormat("[FSASSETS]: Write cycle complete, {0} files, {1} ticks, avg {2:F2}", files.Length, totalTicks, (double)totalTicks / (double)files.Length); | 351 | m_log.InfoFormat("[ASSET]: Write cycle complete, {0} files, {1} ticks, avg {2:F2}", files.Length, totalTicks, (double)totalTicks / (double)files.Length); |
275 | } | 352 | } |
276 | } | 353 | } |
277 | 354 | ||
@@ -291,20 +368,27 @@ namespace OpenSim.Services.FSAssetService | |||
291 | if (hash == null || hash.Length < 10) | 368 | if (hash == null || hash.Length < 10) |
292 | return "junkyard"; | 369 | return "junkyard"; |
293 | 370 | ||
294 | return Path.Combine(hash.Substring(0, 3), | 371 | if (m_useOsgridFormat) |
295 | Path.Combine(hash.Substring(3, 3))); | 372 | { |
296 | /* | 373 | /* |
297 | * The below is what core would normally use. | 374 | * The code below is the OSGrid code. |
298 | * This is modified to work in OSGrid, as seen | 375 | */ |
299 | * above, because the SRAS data is structured | 376 | return Path.Combine(hash.Substring(0, 3), |
300 | * that way. | 377 | Path.Combine(hash.Substring(3, 3))); |
301 | */ | 378 | } |
302 | /* | 379 | else |
303 | return Path.Combine(hash.Substring(0, 2), | 380 | { |
304 | Path.Combine(hash.Substring(2, 2), | 381 | /* |
305 | Path.Combine(hash.Substring(4, 2), | 382 | * The below is what core would normally use. |
306 | hash.Substring(6, 4)))); | 383 | * This is modified to work in OSGrid, as seen |
307 | */ | 384 | * above, because the SRAS data is structured |
385 | * that way. | ||
386 | */ | ||
387 | return Path.Combine(hash.Substring(0, 2), | ||
388 | Path.Combine(hash.Substring(2, 2), | ||
389 | Path.Combine(hash.Substring(4, 2), | ||
390 | hash.Substring(6, 4)))); | ||
391 | } | ||
308 | } | 392 | } |
309 | 393 | ||
310 | private bool AssetExists(string hash) | 394 | private bool AssetExists(string hash) |
@@ -365,7 +449,7 @@ namespace OpenSim.Services.FSAssetService | |||
365 | Store(asset); | 449 | Store(asset); |
366 | } | 450 | } |
367 | } | 451 | } |
368 | if (asset == null) | 452 | if (asset == null && m_showStats) |
369 | { | 453 | { |
370 | // m_log.InfoFormat("[FSASSETS]: Asset {0} not found", id); | 454 | // m_log.InfoFormat("[FSASSETS]: Asset {0} not found", id); |
371 | m_missingAssets++; | 455 | m_missingAssets++; |
@@ -393,8 +477,11 @@ namespace OpenSim.Services.FSAssetService | |||
393 | } | 477 | } |
394 | } | 478 | } |
395 | if (asset == null) | 479 | if (asset == null) |
396 | m_missingAssetsFS++; | 480 | { |
397 | // m_log.InfoFormat("[FSASSETS]: Asset {0}, hash {1} not found in FS", id, hash); | 481 | if (m_showStats) |
482 | m_missingAssetsFS++; | ||
483 | // m_log.InfoFormat("[FSASSETS]: Asset {0}, hash {1} not found in FS", id, hash); | ||
484 | } | ||
398 | else | 485 | else |
399 | { | 486 | { |
400 | // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) | 487 | // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) |
@@ -408,10 +495,13 @@ namespace OpenSim.Services.FSAssetService | |||
408 | } | 495 | } |
409 | } | 496 | } |
410 | 497 | ||
411 | lock (m_statsLock) | 498 | if (m_showStats) |
412 | { | 499 | { |
413 | m_readTicks += Environment.TickCount - startTime; | 500 | lock (m_statsLock) |
414 | m_readCount++; | 501 | { |
502 | m_readTicks += Environment.TickCount - startTime; | ||
503 | m_readCount++; | ||
504 | } | ||
415 | } | 505 | } |
416 | 506 | ||
417 | // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) | 507 | // Deal with bug introduced in Oct. 20 (1eb3e6cc43e2a7b4053bc1185c7c88e22356c5e8) |
@@ -578,6 +668,9 @@ namespace OpenSim.Services.FSAssetService | |||
578 | 668 | ||
579 | if (!m_DataConnector.Store(asset.Metadata, hash)) | 669 | if (!m_DataConnector.Store(asset.Metadata, hash)) |
580 | { | 670 | { |
671 | if (asset.Metadata.Type == -2) | ||
672 | return asset.ID; | ||
673 | |||
581 | return UUID.Zero.ToString(); | 674 | return UUID.Zero.ToString(); |
582 | } | 675 | } |
583 | else | 676 | else |
@@ -630,7 +723,7 @@ namespace OpenSim.Services.FSAssetService | |||
630 | AssetBase asset = Get(args[2], out hash); | 723 | AssetBase asset = Get(args[2], out hash); |
631 | 724 | ||
632 | if (asset == null || asset.Data.Length == 0) | 725 | if (asset == null || asset.Data.Length == 0) |
633 | { | 726 | { |
634 | MainConsole.Instance.Output("Asset not found"); | 727 | MainConsole.Instance.Output("Asset not found"); |
635 | return; | 728 | return; |
636 | } | 729 | } |
@@ -672,7 +765,7 @@ namespace OpenSim.Services.FSAssetService | |||
672 | AssetBase asset = Get(args[2]); | 765 | AssetBase asset = Get(args[2]); |
673 | 766 | ||
674 | if (asset == null || asset.Data.Length == 0) | 767 | if (asset == null || asset.Data.Length == 0) |
675 | { | 768 | { |
676 | MainConsole.Instance.Output("Asset not found"); | 769 | MainConsole.Instance.Output("Asset not found"); |
677 | return; | 770 | return; |
678 | } | 771 | } |