aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL/MySQLFSAssetData.cs
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/Data/MySQL/MySQLFSAssetData.cs
parentMantis 7833: Fix a condition where email sent from an object that is in (diff)
downloadopensim-SC-74c2113bcedb3c55a509b506b15d6ec46607a34e.zip
opensim-SC-74c2113bcedb3c55a509b506b15d6ec46607a34e.tar.gz
opensim-SC-74c2113bcedb3c55a509b506b15d6ec46607a34e.tar.bz2
opensim-SC-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 '')
-rw-r--r--OpenSim/Data/MySQL/MySQLFSAssetData.cs379
1 files changed, 191 insertions, 188 deletions
diff --git a/OpenSim/Data/MySQL/MySQLFSAssetData.cs b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
index 19e23b5..40bfd1f 100644
--- a/OpenSim/Data/MySQL/MySQLFSAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
@@ -41,10 +41,8 @@ namespace OpenSim.Data.MySQL
41 { 41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 protected MySqlConnection m_Connection = null;
45 protected string m_ConnectionString; 44 protected string m_ConnectionString;
46 protected string m_Table; 45 protected string m_Table;
47 protected Object m_connLock = new Object();
48 46
49 /// <summary> 47 /// <summary>
50 /// Number of days that must pass before we update the access time on an asset when it has been fetched 48 /// Number of days that must pass before we update the access time on an asset when it has been fetched
@@ -75,10 +73,11 @@ namespace OpenSim.Data.MySQL
75 73
76 try 74 try
77 { 75 {
78 OpenDatabase(); 76 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
79 77 {
80 Migration m = new Migration(m_Connection, Assembly, "FSAssetStore"); 78 Migration m = new Migration(conn, Assembly, "FSAssetStore");
81 m.Update(); 79 m.Update();
80 }
82 } 81 }
83 catch (MySqlException e) 82 catch (MySqlException e)
84 { 83 {
@@ -100,70 +99,33 @@ namespace OpenSim.Data.MySQL
100 99
101 #endregion 100 #endregion
102 101
103 private bool OpenDatabase() 102 private bool ExecuteNonQuery(MySqlCommand cmd)
104 {
105 try
106 {
107 m_Connection = new MySqlConnection(m_ConnectionString);
108
109 m_Connection.Open();
110 }
111 catch (MySqlException e)
112 {
113 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}",
114 e.Message.ToString());
115
116 return false;
117 }
118
119 return true;
120 }
121
122 private IDataReader ExecuteReader(MySqlCommand c)
123 {
124 IDataReader r = null;
125 MySqlConnection connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
126 connection.Open();
127 c.Connection = connection;
128
129 r = c.ExecuteReader();
130
131 return r;
132 }
133
134 private void ExecuteNonQuery(MySqlCommand c)
135 { 103 {
136 lock (m_connLock) 104 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
137 { 105 {
138 bool errorSeen = false; 106 try
139
140 while (true)
141 { 107 {
142 try 108 conn.Open();
143 { 109 }
144 c.ExecuteNonQuery(); 110 catch (MySqlException e)
145 } 111 {
146 catch (MySqlException) 112 m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString());
147 { 113 return false;
148 System.Threading.Thread.Sleep(500); 114 }
149
150 m_Connection.Close();
151 m_Connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
152 m_Connection.Open();
153 c.Connection = m_Connection;
154
155 if (!errorSeen)
156 {
157 errorSeen = true;
158 continue;
159 }
160 m_log.ErrorFormat("[FSASSETS] MySQL command: {0}", c.CommandText);
161 throw;
162 }
163 115
164 break; 116 cmd.Connection = conn;
117 try
118 {
119 cmd.ExecuteNonQuery();
120 }
121 catch (MySqlException e)
122 {
123 m_log.ErrorFormat("[FSASSETS]: Query {0} failed with {1}", cmd.CommandText, e.ToString());
124 return false;
165 } 125 }
166 } 126 }
127
128 return true;
167 } 129 }
168 130
169 #region IFSAssetDataPlugin Members 131 #region IFSAssetDataPlugin Members
@@ -172,63 +134,78 @@ namespace OpenSim.Data.MySQL
172 { 134 {
173 hash = String.Empty; 135 hash = String.Empty;
174 136
175 MySqlCommand cmd = new MySqlCommand(); 137 AssetMetadata meta = new AssetMetadata();
176
177 cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, access_time, asset_flags from {0} where id = ?id", m_Table);
178 cmd.Parameters.AddWithValue("?id", id);
179
180 IDataReader reader = ExecuteReader(cmd);
181 138
182 if (!reader.Read()) 139 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
183 { 140 {
184 reader.Close(); 141 try
185 FreeCommand(cmd); 142 {
186 return null; 143 conn.Open();
187 } 144 }
188 145 catch (MySqlException e)
189 AssetMetadata meta = new AssetMetadata(); 146 {
147 m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString());
148 return null;
149 }
190 150
191 hash = reader["hash"].ToString(); 151 using (MySqlCommand cmd = conn.CreateCommand())
152 {
153 cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, asset_flags from {0} where id = ?id", m_Table);
154 cmd.Parameters.AddWithValue("?id", id);
192 155
193 meta.ID = id; 156 using (IDataReader reader = cmd.ExecuteReader())
194 meta.FullID = new UUID(id); 157 {
158 if (!reader.Read())
159 return null;
195 160
196 meta.Name = reader["name"].ToString(); 161 hash = reader["hash"].ToString();
197 meta.Description = reader["description"].ToString();
198 meta.Type = (sbyte)Convert.ToInt32(reader["type"]);
199 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
200 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
201 meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]);
202 162
203 int AccessTime = Convert.ToInt32(reader["access_time"]); 163 meta.ID = id;
164 meta.FullID = new UUID(id);
204 165
205 reader.Close(); 166 meta.Name = reader["name"].ToString();
167 meta.Description = reader["description"].ToString();
168 meta.Type = (sbyte)Convert.ToInt32(reader["type"]);
169 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
170 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
171 meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]);
206 172
207 UpdateAccessTime(AccessTime, cmd); 173 int AccessTime = Convert.ToInt32(reader["access_time"]);
174 UpdateAccessTime(AccessTime);
175 }
176 }
208 177
209 FreeCommand(cmd); 178 }
210 179
211 return meta; 180 return meta;
212 } 181 }
213 182
214 private void UpdateAccessTime(int AccessTime, MySqlCommand cmd) 183 private void UpdateAccessTime(int AccessTime)
215 { 184 {
216 // Reduce DB work by only updating access time if asset hasn't recently been accessed 185 // Reduce DB work by only updating access time if asset hasn't recently been accessed
217 // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates" 186 // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates"
218 if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates) 187 if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
219 return; 188 return;
220 189
221 cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table); 190 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
191 {
192 try
193 {
194 conn.Open();
195 }
196 catch (MySqlException e)
197 {
198 m_log.ErrorFormat("[FSASSETS]: Database open failed with {0}", e.ToString());
199 return;
200 }
222 201
223 cmd.ExecuteNonQuery(); 202 using (MySqlCommand cmd = conn.CreateCommand())
224 } 203 {
204 cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table);
225 205
226 protected void FreeCommand(MySqlCommand cmd) 206 cmd.ExecuteNonQuery();
227 { 207 }
228 MySqlConnection c = cmd.Connection; 208 }
229 cmd.Dispose();
230 c.Close();
231 c.Dispose();
232 } 209 }
233 210
234 public bool Store(AssetMetadata meta, string hash) 211 public bool Store(AssetMetadata meta, string hash)
@@ -238,37 +215,35 @@ namespace OpenSim.Data.MySQL
238 string oldhash; 215 string oldhash;
239 AssetMetadata existingAsset = Get(meta.ID, out oldhash); 216 AssetMetadata existingAsset = Get(meta.ID, out oldhash);
240 217
241 MySqlCommand cmd = m_Connection.CreateCommand(); 218 using (MySqlCommand cmd = new MySqlCommand())
242
243 cmd.Parameters.AddWithValue("?id", meta.ID);
244 cmd.Parameters.AddWithValue("?name", meta.Name);
245 cmd.Parameters.AddWithValue("?description", meta.Description);
246 cmd.Parameters.AddWithValue("?type", meta.Type.ToString());
247 cmd.Parameters.AddWithValue("?hash", hash);
248 cmd.Parameters.AddWithValue("?asset_flags", meta.Flags);
249
250 if (existingAsset == null)
251 { 219 {
252 cmd.CommandText = String.Format("insert into {0} (id, name, description, type, hash, asset_flags, create_time, access_time) values ( ?id, ?name, ?description, ?type, ?hash, ?asset_flags, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())", m_Table); 220 cmd.Parameters.AddWithValue("?id", meta.ID);
253 221 cmd.Parameters.AddWithValue("?name", meta.Name);
254 ExecuteNonQuery(cmd); 222 cmd.Parameters.AddWithValue("?description", meta.Description);
223 cmd.Parameters.AddWithValue("?type", meta.Type.ToString());
224 cmd.Parameters.AddWithValue("?hash", hash);
225 cmd.Parameters.AddWithValue("?asset_flags", meta.Flags);
226
227 if (existingAsset == null)
228 {
229 cmd.CommandText = String.Format("insert into {0} (id, name, description, type, hash, asset_flags, create_time, access_time) values ( ?id, ?name, ?description, ?type, ?hash, ?asset_flags, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())", m_Table);
255 230
256 cmd.Dispose(); 231 ExecuteNonQuery(cmd);
257 232
258 return true; 233 return true;
259 } 234 }
260 235
261 //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table); 236 //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table);
262 237
263 //ExecuteNonQuery(cmd); 238 //ExecuteNonQuery(cmd);
264 239
265 cmd.Dispose(); 240 }
266 return false; 241 return false;
267 } 242 }
268 catch(Exception e) 243 catch(Exception e)
269 { 244 {
270 m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID); 245 m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID);
271 m_log.Error(e.ToString()); 246 m_log.Error(e.ToString());
272 return false; 247 return false;
273 } 248 }
274 } 249 }
@@ -283,26 +258,42 @@ namespace OpenSim.Data.MySQL
283 if (uuids.Length == 0) 258 if (uuids.Length == 0)
284 return new bool[0]; 259 return new bool[0];
285 260
261 bool[] results = new bool[uuids.Length];
262 for (int i = 0; i < uuids.Length; i++)
263 results[i] = false;
264
286 HashSet<UUID> exists = new HashSet<UUID>(); 265 HashSet<UUID> exists = new HashSet<UUID>();
287 266
288 string ids = "'" + string.Join("','", uuids) + "'"; 267 string ids = "'" + string.Join("','", uuids) + "'";
289 string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table); 268 string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table);
290 269
291 using (MySqlCommand cmd = m_Connection.CreateCommand()) 270 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
292 { 271 {
293 cmd.CommandText = sql; 272 try
273 {
274 conn.Open();
275 }
276 catch (MySqlException e)
277 {
278 m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString());
279 return results;
280 }
294 281
295 using (MySqlDataReader dbReader = cmd.ExecuteReader()) 282 using (MySqlCommand cmd = conn.CreateCommand())
296 { 283 {
297 while (dbReader.Read()) 284 cmd.CommandText = sql;
285
286 using (MySqlDataReader dbReader = cmd.ExecuteReader())
298 { 287 {
299 UUID id = DBGuid.FromDB(dbReader["ID"]); 288 while (dbReader.Read())
300 exists.Add(id); 289 {
290 UUID id = DBGuid.FromDB(dbReader["ID"]);
291 exists.Add(id);
292 }
301 } 293 }
302 } 294 }
303 } 295 }
304 296
305 bool[] results = new bool[uuids.Length];
306 for (int i = 0; i < uuids.Length; i++) 297 for (int i = 0; i < uuids.Length; i++)
307 results[i] = exists.Contains(uuids[i]); 298 results[i] = exists.Contains(uuids[i]);
308 return results; 299 return results;
@@ -310,102 +301,114 @@ namespace OpenSim.Data.MySQL
310 301
311 public int Count() 302 public int Count()
312 { 303 {
313 MySqlCommand cmd = m_Connection.CreateCommand(); 304 int count = 0;
314 305
315 cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table); 306 using (MySqlConnection conn = new MySqlConnection(m_ConnectionString))
307 {
308 try
309 {
310 conn.Open();
311 }
312 catch (MySqlException e)
313 {
314 m_log.ErrorFormat("[FSASSETS]: Failed to open database: {0}", e.ToString());
315 return 0;
316 }
316 317
317 IDataReader reader = ExecuteReader(cmd); 318 MySqlCommand cmd = conn.CreateCommand();
318 319
319 reader.Read(); 320 cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table);
320 321
321 int count = Convert.ToInt32(reader["count"]); 322 using (IDataReader reader = cmd.ExecuteReader())
323 {
324 reader.Read();
322 325
323 reader.Close(); 326 count = Convert.ToInt32(reader["count"]);
324 FreeCommand(cmd); 327 }
328 }
325 329
326 return count; 330 return count;
327 } 331 }
328 332
329 public bool Delete(string id) 333 public bool Delete(string id)
330 { 334 {
331 using (MySqlCommand cmd = m_Connection.CreateCommand()) 335 MySqlCommand cmd = new MySqlCommand();
332 {
333 cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table);
334 336
335 cmd.Parameters.AddWithValue("?id", id); 337 cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table);
336 338
337 ExecuteNonQuery(cmd); 339 cmd.Parameters.AddWithValue("?id", id);
338 } 340
341 ExecuteNonQuery(cmd);
342
343 cmd.Dispose();
339 344
340 return true; 345 return true;
341 } 346 }
342 347
343 public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store) 348 public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store)
344 { 349 {
345 MySqlConnection importConn; 350 int imported = 0;
346
347 try
348 {
349 importConn = new MySqlConnection(conn);
350 351
351 importConn.Open(); 352 using (MySqlConnection importConn = new MySqlConnection(conn))
352 }
353 catch (MySqlException e)
354 { 353 {
355 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", 354 try
356 e.Message.ToString()); 355 {
356 importConn.Open();
357 }
358 catch (MySqlException e)
359 {
360 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}",
361 e.Message.ToString());
357 362
358 return; 363 return;
359 } 364 }
360 365
361 int imported = 0; 366 using (MySqlCommand cmd = importConn.CreateCommand())
367 {
368 string limit = String.Empty;
369 if (count != -1)
370 {
371 limit = String.Format(" limit {0},{1}", start, count);
372 }
362 373
363 MySqlCommand cmd = importConn.CreateCommand(); 374 cmd.CommandText = String.Format("select * from {0}{1}", table, limit);
364 375
365 string limit = String.Empty; 376 MainConsole.Instance.Output("Querying database");
366 if (count != -1) 377 using (IDataReader reader = cmd.ExecuteReader())
367 { 378 {
368 limit = String.Format(" limit {0},{1}", start, count); 379 MainConsole.Instance.Output("Reading data");
369 }
370
371 cmd.CommandText = String.Format("select * from {0}{1}", table, limit);
372 380
373 MainConsole.Instance.Output("Querying database"); 381 while (reader.Read())
374 IDataReader reader = cmd.ExecuteReader(); 382 {
383 if ((imported % 100) == 0)
384 {
385 MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported));
386 }
375 387
376 MainConsole.Instance.Output("Reading data"); 388 AssetBase asset = new AssetBase();
389 AssetMetadata meta = new AssetMetadata();
377 390
378 while (reader.Read()) 391 meta.ID = reader["id"].ToString();
379 { 392 meta.FullID = new UUID(meta.ID);
380 if ((imported % 100) == 0)
381 {
382 MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported));
383 }
384
385 AssetBase asset = new AssetBase();
386 AssetMetadata meta = new AssetMetadata();
387 393
388 meta.ID = reader["id"].ToString(); 394 meta.Name = reader["name"].ToString();
389 meta.FullID = new UUID(meta.ID); 395 meta.Description = reader["description"].ToString();
396 meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]);
397 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
398 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
390 399
391 meta.Name = reader["name"].ToString(); 400 asset.Metadata = meta;
392 meta.Description = reader["description"].ToString(); 401 asset.Data = (byte[])reader["data"];
393 meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]);
394 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
395 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
396 402
397 asset.Metadata = meta; 403 store(asset, force);
398 asset.Data = (byte[])reader["data"];
399 404
400 store(asset, force); 405 imported++;
406 }
407 }
401 408
402 imported++; 409 }
403 } 410 }
404 411
405 reader.Close();
406 cmd.Dispose();
407 importConn.Close();
408
409 MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported)); 412 MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported));
410 } 413 }
411 414