aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/FSAssetService
diff options
context:
space:
mode:
authorMelanie Thielker2016-03-05 01:17:42 +0100
committerMelanie Thielker2016-03-05 01:17:42 +0100
commit74c2113bcedb3c55a509b506b15d6ec46607a34e (patch)
tree337a9e3999eefc58c8c5824750afdb57ee43f36f /OpenSim/Services/FSAssetService
parentMantis 7833: Fix a condition where email sent from an object that is in (diff)
downloadopensim-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.cs118
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)