diff options
author | Melanie Thielker | 2016-03-05 01:17:42 +0100 |
---|---|---|
committer | Melanie Thielker | 2016-03-05 01:17:42 +0100 |
commit | 74c2113bcedb3c55a509b506b15d6ec46607a34e (patch) | |
tree | 337a9e3999eefc58c8c5824750afdb57ee43f36f /OpenSim/Services/FSAssetService | |
parent | Mantis 7833: Fix a condition where email sent from an object that is in (diff) | |
download | opensim-SC_OLD-74c2113bcedb3c55a509b506b15d6ec46607a34e.zip opensim-SC_OLD-74c2113bcedb3c55a509b506b15d6ec46607a34e.tar.gz opensim-SC_OLD-74c2113bcedb3c55a509b506b15d6ec46607a34e.tar.bz2 opensim-SC_OLD-74c2113bcedb3c55a509b506b15d6ec46607a34e.tar.xz |
Port the safer database access and the cure for "Chicken Bones" which
are artefacts that can be created by fsck and would make standard
FSAssets choke. These refinements were tested on OSGrid.
Diffstat (limited to 'OpenSim/Services/FSAssetService')
-rw-r--r-- | OpenSim/Services/FSAssetService/FSAssetService.cs | 118 |
1 files changed, 94 insertions, 24 deletions
diff --git a/OpenSim/Services/FSAssetService/FSAssetService.cs b/OpenSim/Services/FSAssetService/FSAssetService.cs index 1bab687..bf7ddff 100644 --- a/OpenSim/Services/FSAssetService/FSAssetService.cs +++ b/OpenSim/Services/FSAssetService/FSAssetService.cs | |||
@@ -119,8 +119,8 @@ namespace OpenSim.Services.FSAssetService | |||
119 | 119 | ||
120 | // Get Database Connector from Asset Config (If present) | 120 | // Get Database Connector from Asset Config (If present) |
121 | string dllName = assetConfig.GetString("StorageProvider", string.Empty); | 121 | string dllName = assetConfig.GetString("StorageProvider", string.Empty); |
122 | string m_ConnectionString = assetConfig.GetString("ConnectionString", string.Empty); | 122 | string connectionString = assetConfig.GetString("ConnectionString", string.Empty); |
123 | string m_Realm = assetConfig.GetString("Realm", "fsassets"); | 123 | string realm = assetConfig.GetString("Realm", "fsassets"); |
124 | 124 | ||
125 | int SkipAccessTimeDays = assetConfig.GetInt("DaysBetweenAccessTimeUpdates", 0); | 125 | int SkipAccessTimeDays = assetConfig.GetInt("DaysBetweenAccessTimeUpdates", 0); |
126 | 126 | ||
@@ -132,15 +132,15 @@ namespace OpenSim.Services.FSAssetService | |||
132 | if (dllName == String.Empty) | 132 | if (dllName == String.Empty) |
133 | dllName = dbConfig.GetString("StorageProvider", String.Empty); | 133 | dllName = dbConfig.GetString("StorageProvider", String.Empty); |
134 | 134 | ||
135 | if (m_ConnectionString == String.Empty) | 135 | if (connectionString == String.Empty) |
136 | m_ConnectionString = dbConfig.GetString("ConnectionString", String.Empty); | 136 | connectionString = dbConfig.GetString("ConnectionString", String.Empty); |
137 | } | 137 | } |
138 | 138 | ||
139 | // No databse connection found in either config | 139 | // No databse connection found in either config |
140 | if (dllName.Equals(String.Empty)) | 140 | if (dllName.Equals(String.Empty)) |
141 | throw new Exception("No StorageProvider configured"); | 141 | throw new Exception("No StorageProvider configured"); |
142 | 142 | ||
143 | if (m_ConnectionString.Equals(String.Empty)) | 143 | if (connectionString.Equals(String.Empty)) |
144 | throw new Exception("Missing database connection string"); | 144 | throw new Exception("Missing database connection string"); |
145 | 145 | ||
146 | // Create Storage Provider | 146 | // Create Storage Provider |
@@ -150,7 +150,7 @@ namespace OpenSim.Services.FSAssetService | |||
150 | throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); | 150 | throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); |
151 | 151 | ||
152 | // Initialize DB And perform any migrations required | 152 | // Initialize DB And perform any migrations required |
153 | m_DataConnector.Initialise(m_ConnectionString, m_Realm, SkipAccessTimeDays); | 153 | m_DataConnector.Initialise(connectionString, realm, SkipAccessTimeDays); |
154 | 154 | ||
155 | // Setup Fallback Service | 155 | // Setup Fallback Service |
156 | string str = assetConfig.GetString("FallbackService", string.Empty); | 156 | string str = assetConfig.GetString("FallbackService", string.Empty); |
@@ -232,7 +232,7 @@ namespace OpenSim.Services.FSAssetService | |||
232 | 232 | ||
233 | private void Writer() | 233 | private void Writer() |
234 | { | 234 | { |
235 | m_log.Info("[FSASSETS]: Writer started"); | 235 | m_log.Info("[ASSET]: Writer started"); |
236 | 236 | ||
237 | while (true) | 237 | while (true) |
238 | { | 238 | { |
@@ -246,33 +246,98 @@ namespace OpenSim.Services.FSAssetService | |||
246 | string hash = Path.GetFileNameWithoutExtension(files[i]); | 246 | string hash = Path.GetFileNameWithoutExtension(files[i]); |
247 | string s = HashToFile(hash); | 247 | string s = HashToFile(hash); |
248 | string diskFile = Path.Combine(m_FSBase, s); | 248 | string diskFile = Path.Combine(m_FSBase, s); |
249 | bool pathOk = false; | ||
249 | 250 | ||
250 | Directory.CreateDirectory(Path.GetDirectoryName(diskFile)); | 251 | // The cure for chicken bones! |
251 | try | 252 | while(true) |
252 | { | 253 | { |
253 | byte[] data = File.ReadAllBytes(files[i]); | 254 | try |
254 | |||
255 | using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Create), CompressionMode.Compress)) | ||
256 | { | 255 | { |
257 | gz.Write(data, 0, data.Length); | 256 | // Try to make the directory we need for this file |
258 | gz.Close(); | 257 | Directory.CreateDirectory(Path.GetDirectoryName(diskFile)); |
258 | pathOk = true; | ||
259 | break; | ||
259 | } | 260 | } |
260 | File.Delete(files[i]); | 261 | catch (System.IO.IOException) |
261 | 262 | { | |
262 | //File.Move(files[i], diskFile); | 263 | // Creating the directory failed. This can't happen unless |
264 | // a part of the path already exists as a file. Sadly the | ||
265 | // SRAS data contains such files. | ||
266 | string d = Path.GetDirectoryName(diskFile); | ||
267 | |||
268 | // Test each path component in turn. If we can successfully | ||
269 | // make a directory, the level below must be the chicken bone. | ||
270 | while (d.Length > 0) | ||
271 | { | ||
272 | Console.WriteLine(d); | ||
273 | try | ||
274 | { | ||
275 | Directory.CreateDirectory(Path.GetDirectoryName(d)); | ||
276 | } | ||
277 | catch (System.IO.IOException) | ||
278 | { | ||
279 | d = Path.GetDirectoryName(d); | ||
280 | |||
281 | // We failed making the directory and need to | ||
282 | // go up a bit more | ||
283 | continue; | ||
284 | } | ||
285 | |||
286 | // We succeeded in making the directory and (d) is | ||
287 | // the chicken bone | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | // Is the chicken alive? | ||
292 | if (d.Length > 0) | ||
293 | { | ||
294 | Console.WriteLine(d); | ||
295 | |||
296 | FileAttributes attr = File.GetAttributes(d); | ||
297 | |||
298 | if ((attr & FileAttributes.Directory) == 0) | ||
299 | { | ||
300 | // The chicken bone should be resolved. | ||
301 | // Return to writing the file. | ||
302 | File.Delete(d); | ||
303 | continue; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | // Could not resolve, skipping | ||
308 | m_log.ErrorFormat("[ASSET]: Could not resolve path creation error for {0}", diskFile); | ||
309 | break; | ||
263 | } | 310 | } |
264 | catch(System.IO.IOException e) | 311 | |
312 | if (pathOk) | ||
265 | { | 313 | { |
266 | if (e.Message.StartsWith("Win32 IO returned ERROR_ALREADY_EXISTS")) | 314 | try |
315 | { | ||
316 | byte[] data = File.ReadAllBytes(files[i]); | ||
317 | |||
318 | using (GZipStream gz = new GZipStream(new FileStream(diskFile + ".gz", FileMode.Create), CompressionMode.Compress)) | ||
319 | { | ||
320 | gz.Write(data, 0, data.Length); | ||
321 | gz.Close(); | ||
322 | } | ||
267 | File.Delete(files[i]); | 323 | File.Delete(files[i]); |
268 | else | 324 | |
269 | throw; | 325 | //File.Move(files[i], diskFile); |
326 | } | ||
327 | catch(System.IO.IOException e) | ||
328 | { | ||
329 | if (e.Message.StartsWith("Win32 IO returned ERROR_ALREADY_EXISTS")) | ||
330 | File.Delete(files[i]); | ||
331 | else | ||
332 | throw; | ||
333 | } | ||
270 | } | 334 | } |
271 | } | 335 | } |
336 | |||
272 | int totalTicks = System.Environment.TickCount - tickCount; | 337 | int totalTicks = System.Environment.TickCount - tickCount; |
273 | if (totalTicks > 0) // Wrap? | 338 | if (totalTicks > 0) // Wrap? |
274 | { | 339 | { |
275 | m_log.InfoFormat("[FSASSETS]: Write cycle complete, {0} files, {1} ticks, avg {2:F2}", files.Length, totalTicks, (double)totalTicks / (double)files.Length); | 340 | m_log.InfoFormat("[ASSET]: Write cycle complete, {0} files, {1} ticks, avg {2:F2}", files.Length, totalTicks, (double)totalTicks / (double)files.Length); |
276 | } | 341 | } |
277 | } | 342 | } |
278 | 343 | ||
@@ -292,20 +357,25 @@ namespace OpenSim.Services.FSAssetService | |||
292 | if (hash == null || hash.Length < 10) | 357 | if (hash == null || hash.Length < 10) |
293 | return "junkyard"; | 358 | return "junkyard"; |
294 | 359 | ||
360 | /* | ||
361 | * The code below is the OSGrid code. | ||
362 | * This should probably become a config option. | ||
363 | */ | ||
364 | /* | ||
295 | return Path.Combine(hash.Substring(0, 3), | 365 | return Path.Combine(hash.Substring(0, 3), |
296 | Path.Combine(hash.Substring(3, 3))); | 366 | Path.Combine(hash.Substring(3, 3))); |
367 | */ | ||
368 | |||
297 | /* | 369 | /* |
298 | * The below is what core would normally use. | 370 | * The below is what core would normally use. |
299 | * This is modified to work in OSGrid, as seen | 371 | * This is modified to work in OSGrid, as seen |
300 | * above, because the SRAS data is structured | 372 | * above, because the SRAS data is structured |
301 | * that way. | 373 | * that way. |
302 | */ | 374 | */ |
303 | /* | ||
304 | return Path.Combine(hash.Substring(0, 2), | 375 | return Path.Combine(hash.Substring(0, 2), |
305 | Path.Combine(hash.Substring(2, 2), | 376 | Path.Combine(hash.Substring(2, 2), |
306 | Path.Combine(hash.Substring(4, 2), | 377 | Path.Combine(hash.Substring(4, 2), |
307 | hash.Substring(6, 4)))); | 378 | hash.Substring(6, 4)))); |
308 | */ | ||
309 | } | 379 | } |
310 | 380 | ||
311 | private bool AssetExists(string hash) | 381 | private bool AssetExists(string hash) |