diff options
author | Master ScienceSim | 2010-02-04 13:19:30 -0800 |
---|---|---|
committer | John Hurliman | 2010-02-05 18:07:59 -0800 |
commit | e1b5c612472b9d1acf47383c0bf75b555daff2e6 (patch) | |
tree | 083896698038fbdad59c2bd3adeba9b290c5ce1b /OpenSim/Data/MySQL/MySQLAssetData.cs | |
parent | Fixing an incorrect logging message in insertUserRow (diff) | |
download | opensim-SC-e1b5c612472b9d1acf47383c0bf75b555daff2e6.zip opensim-SC-e1b5c612472b9d1acf47383c0bf75b555daff2e6.tar.gz opensim-SC-e1b5c612472b9d1acf47383c0bf75b555daff2e6.tar.bz2 opensim-SC-e1b5c612472b9d1acf47383c0bf75b555daff2e6.tar.xz |
Updated MySQL connection management to use the MySQL connection pooling. This should accommodate various timeout problems that exist with the current connection pool code in a more general and standard way.
Diffstat (limited to 'OpenSim/Data/MySQL/MySQLAssetData.cs')
-rw-r--r-- | OpenSim/Data/MySQL/MySQLAssetData.cs | 355 |
1 files changed, 158 insertions, 197 deletions
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index 6a4ccd7..666c22f 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs | |||
@@ -43,10 +43,13 @@ namespace OpenSim.Data.MySQL | |||
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | 45 | ||
46 | private MySQLManager _dbConnection; | 46 | private string m_connectionString; |
47 | private object m_dbLock = new object(); | ||
47 | 48 | ||
48 | #region IPlugin Members | 49 | #region IPlugin Members |
49 | 50 | ||
51 | public override string Version { get { return "1.0.0.0"; } } | ||
52 | |||
50 | /// <summary> | 53 | /// <summary> |
51 | /// <para>Initialises Asset interface</para> | 54 | /// <para>Initialises Asset interface</para> |
52 | /// <para> | 55 | /// <para> |
@@ -58,63 +61,29 @@ namespace OpenSim.Data.MySQL | |||
58 | /// </para> | 61 | /// </para> |
59 | /// </summary> | 62 | /// </summary> |
60 | /// <param name="connect">connect string</param> | 63 | /// <param name="connect">connect string</param> |
61 | override public void Initialise(string connect) | 64 | public override void Initialise(string connect) |
62 | { | 65 | { |
63 | // TODO: This will let you pass in the connect string in | 66 | m_connectionString = connect; |
64 | // the config, though someone will need to write that. | ||
65 | if (connect == String.Empty) | ||
66 | { | ||
67 | // This is old seperate config file | ||
68 | m_log.Warn("no connect string, using old mysql_connection.ini instead"); | ||
69 | Initialise(); | ||
70 | } | ||
71 | else | ||
72 | { | ||
73 | _dbConnection = new MySQLManager(connect); | ||
74 | } | ||
75 | 67 | ||
76 | // This actually does the roll forward assembly stuff | 68 | // This actually does the roll forward assembly stuff |
77 | Assembly assem = GetType().Assembly; | 69 | Assembly assem = GetType().Assembly; |
78 | Migration m = new Migration(_dbConnection.Connection, assem, "AssetStore"); | ||
79 | 70 | ||
80 | m.Update(); | 71 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
72 | { | ||
73 | dbcon.Open(); | ||
74 | Migration m = new Migration(dbcon, assem, "AssetStore"); | ||
75 | m.Update(); | ||
76 | } | ||
81 | } | 77 | } |
82 | 78 | ||
83 | /// <summary> | ||
84 | /// <para>Initialises Asset interface</para> | ||
85 | /// <para> | ||
86 | /// <list type="bullet"> | ||
87 | /// <item>Loads and initialises the MySQL storage plugin</item> | ||
88 | /// <item>uses the obsolete mysql_connection.ini</item> | ||
89 | /// </list> | ||
90 | /// </para> | ||
91 | /// </summary> | ||
92 | /// <remarks>DEPRECATED and shouldn't be used</remarks> | ||
93 | public override void Initialise() | 79 | public override void Initialise() |
94 | { | 80 | { |
95 | IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); | 81 | throw new NotImplementedException(); |
96 | string hostname = GridDataMySqlFile.ParseFileReadValue("hostname"); | ||
97 | string database = GridDataMySqlFile.ParseFileReadValue("database"); | ||
98 | string username = GridDataMySqlFile.ParseFileReadValue("username"); | ||
99 | string password = GridDataMySqlFile.ParseFileReadValue("password"); | ||
100 | string pooling = GridDataMySqlFile.ParseFileReadValue("pooling"); | ||
101 | string port = GridDataMySqlFile.ParseFileReadValue("port"); | ||
102 | |||
103 | _dbConnection = new MySQLManager(hostname, database, username, password, pooling, port); | ||
104 | |||
105 | } | 82 | } |
106 | 83 | ||
107 | public override void Dispose() { } | 84 | public override void Dispose() { } |
108 | 85 | ||
109 | /// <summary> | 86 | /// <summary> |
110 | /// Database provider version | ||
111 | /// </summary> | ||
112 | override public string Version | ||
113 | { | ||
114 | get { return _dbConnection.getVersion(); } | ||
115 | } | ||
116 | |||
117 | /// <summary> | ||
118 | /// The name of this DB provider | 87 | /// The name of this DB provider |
119 | /// </summary> | 88 | /// </summary> |
120 | override public string Name | 89 | override public string Name |
@@ -135,46 +104,43 @@ namespace OpenSim.Data.MySQL | |||
135 | override public AssetBase GetAsset(UUID assetID) | 104 | override public AssetBase GetAsset(UUID assetID) |
136 | { | 105 | { |
137 | AssetBase asset = null; | 106 | AssetBase asset = null; |
138 | lock (_dbConnection) | 107 | lock (m_dbLock) |
139 | { | 108 | { |
140 | _dbConnection.CheckConnection(); | 109 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
110 | { | ||
111 | dbcon.Open(); | ||
141 | 112 | ||
142 | MySqlCommand cmd = | 113 | using (MySqlCommand cmd = new MySqlCommand( |
143 | new MySqlCommand( | ||
144 | "SELECT name, description, assetType, local, temporary, data FROM assets WHERE id=?id", | 114 | "SELECT name, description, assetType, local, temporary, data FROM assets WHERE id=?id", |
145 | _dbConnection.Connection); | 115 | dbcon)) |
146 | cmd.Parameters.AddWithValue("?id", assetID.ToString()); | ||
147 | |||
148 | try | ||
149 | { | ||
150 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) | ||
151 | { | 116 | { |
152 | if (dbReader.Read()) | 117 | cmd.Parameters.AddWithValue("?id", assetID.ToString()); |
153 | { | ||
154 | asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]); | ||
155 | asset.Data = (byte[]) dbReader["data"]; | ||
156 | asset.Description = (string) dbReader["description"]; | ||
157 | 118 | ||
158 | string local = dbReader["local"].ToString(); | 119 | try |
159 | if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase)) | 120 | { |
160 | asset.Local = true; | 121 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) |
161 | else | 122 | { |
162 | asset.Local = false; | 123 | if (dbReader.Read()) |
163 | 124 | { | |
164 | asset.Temporary = Convert.ToBoolean(dbReader["temporary"]); | 125 | asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]); |
126 | asset.Data = (byte[])dbReader["data"]; | ||
127 | asset.Description = (string)dbReader["description"]; | ||
128 | |||
129 | string local = dbReader["local"].ToString(); | ||
130 | if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase)) | ||
131 | asset.Local = true; | ||
132 | else | ||
133 | asset.Local = false; | ||
134 | |||
135 | asset.Temporary = Convert.ToBoolean(dbReader["temporary"]); | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | catch (Exception e) | ||
140 | { | ||
141 | m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message); | ||
165 | } | 142 | } |
166 | dbReader.Close(); | ||
167 | cmd.Dispose(); | ||
168 | } | 143 | } |
169 | if (asset != null) | ||
170 | UpdateAccessTime(asset); | ||
171 | } | ||
172 | catch (Exception e) | ||
173 | { | ||
174 | m_log.ErrorFormat( | ||
175 | "[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString() | ||
176 | + Environment.NewLine + "Reconnecting", assetID); | ||
177 | _dbConnection.Reconnect(); | ||
178 | } | 144 | } |
179 | } | 145 | } |
180 | return asset; | 146 | return asset; |
@@ -187,55 +153,57 @@ namespace OpenSim.Data.MySQL | |||
187 | /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> | 153 | /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> |
188 | override public void StoreAsset(AssetBase asset) | 154 | override public void StoreAsset(AssetBase asset) |
189 | { | 155 | { |
190 | lock (_dbConnection) | 156 | lock (m_dbLock) |
191 | { | 157 | { |
192 | _dbConnection.CheckConnection(); | 158 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
159 | { | ||
160 | dbcon.Open(); | ||
193 | 161 | ||
194 | MySqlCommand cmd = | 162 | MySqlCommand cmd = |
195 | new MySqlCommand( | 163 | new MySqlCommand( |
196 | "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, data)" + | 164 | "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, data)" + |
197 | "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?data)", | 165 | "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?data)", |
198 | _dbConnection.Connection); | 166 | dbcon); |
199 | 167 | ||
200 | string assetName = asset.Name; | 168 | string assetName = asset.Name; |
201 | if (asset.Name.Length > 64) | 169 | if (asset.Name.Length > 64) |
202 | { | ||
203 | assetName = asset.Name.Substring(0, 64); | ||
204 | m_log.Warn("[ASSET DB]: Name field truncated from " + asset.Name.Length + " to " + assetName.Length + " characters on add"); | ||
205 | } | ||
206 | |||
207 | string assetDescription = asset.Description; | ||
208 | if (asset.Description.Length > 64) | ||
209 | { | ||
210 | assetDescription = asset.Description.Substring(0, 64); | ||
211 | m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add"); | ||
212 | } | ||
213 | |||
214 | // need to ensure we dispose | ||
215 | try | ||
216 | { | ||
217 | using (cmd) | ||
218 | { | 170 | { |
219 | // create unix epoch time | 171 | assetName = asset.Name.Substring(0, 64); |
220 | int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | 172 | m_log.Warn("[ASSET DB]: Name field truncated from " + asset.Name.Length + " to " + assetName.Length + " characters on add"); |
221 | cmd.Parameters.AddWithValue("?id", asset.ID); | 173 | } |
222 | cmd.Parameters.AddWithValue("?name", assetName); | 174 | |
223 | cmd.Parameters.AddWithValue("?description", assetDescription); | 175 | string assetDescription = asset.Description; |
224 | cmd.Parameters.AddWithValue("?assetType", asset.Type); | 176 | if (asset.Description.Length > 64) |
225 | cmd.Parameters.AddWithValue("?local", asset.Local); | 177 | { |
226 | cmd.Parameters.AddWithValue("?temporary", asset.Temporary); | 178 | assetDescription = asset.Description.Substring(0, 64); |
227 | cmd.Parameters.AddWithValue("?create_time", now); | 179 | m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add"); |
228 | cmd.Parameters.AddWithValue("?access_time", now); | 180 | } |
229 | cmd.Parameters.AddWithValue("?data", asset.Data); | 181 | |
230 | cmd.ExecuteNonQuery(); | 182 | // need to ensure we dispose |
231 | cmd.Dispose(); | 183 | try |
184 | { | ||
185 | using (cmd) | ||
186 | { | ||
187 | // create unix epoch time | ||
188 | int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||
189 | cmd.Parameters.AddWithValue("?id", asset.ID); | ||
190 | cmd.Parameters.AddWithValue("?name", assetName); | ||
191 | cmd.Parameters.AddWithValue("?description", assetDescription); | ||
192 | cmd.Parameters.AddWithValue("?assetType", asset.Type); | ||
193 | cmd.Parameters.AddWithValue("?local", asset.Local); | ||
194 | cmd.Parameters.AddWithValue("?temporary", asset.Temporary); | ||
195 | cmd.Parameters.AddWithValue("?create_time", now); | ||
196 | cmd.Parameters.AddWithValue("?access_time", now); | ||
197 | cmd.Parameters.AddWithValue("?data", asset.Data); | ||
198 | cmd.ExecuteNonQuery(); | ||
199 | cmd.Dispose(); | ||
200 | } | ||
201 | } | ||
202 | catch (Exception e) | ||
203 | { | ||
204 | m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}", | ||
205 | asset.FullID, asset.Name, e.Message); | ||
232 | } | 206 | } |
233 | } | ||
234 | catch (Exception e) | ||
235 | { | ||
236 | m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Attempting reconnect. Error: {2}", | ||
237 | asset.FullID, asset.Name, e.Message); | ||
238 | _dbConnection.Reconnect(); | ||
239 | } | 207 | } |
240 | } | 208 | } |
241 | } | 209 | } |
@@ -245,35 +213,36 @@ namespace OpenSim.Data.MySQL | |||
245 | // Writing to the database every time Get() is called on an asset is killing us. Seriously. -jph | 213 | // Writing to the database every time Get() is called on an asset is killing us. Seriously. -jph |
246 | return; | 214 | return; |
247 | 215 | ||
248 | lock (_dbConnection) | 216 | lock (m_dbLock) |
249 | { | 217 | { |
250 | _dbConnection.CheckConnection(); | 218 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
251 | |||
252 | MySqlCommand cmd = | ||
253 | new MySqlCommand("update assets set access_time=?access_time where id=?id", | ||
254 | _dbConnection.Connection); | ||
255 | |||
256 | // need to ensure we dispose | ||
257 | try | ||
258 | { | 219 | { |
259 | using (cmd) | 220 | dbcon.Open(); |
221 | MySqlCommand cmd = | ||
222 | new MySqlCommand("update assets set access_time=?access_time where id=?id", | ||
223 | dbcon); | ||
224 | |||
225 | // need to ensure we dispose | ||
226 | try | ||
227 | { | ||
228 | using (cmd) | ||
229 | { | ||
230 | // create unix epoch time | ||
231 | int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | ||
232 | cmd.Parameters.AddWithValue("?id", asset.ID); | ||
233 | cmd.Parameters.AddWithValue("?access_time", now); | ||
234 | cmd.ExecuteNonQuery(); | ||
235 | cmd.Dispose(); | ||
236 | } | ||
237 | } | ||
238 | catch (Exception e) | ||
260 | { | 239 | { |
261 | // create unix epoch time | 240 | m_log.ErrorFormat( |
262 | int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); | 241 | "[ASSETS DB]: " + |
263 | cmd.Parameters.AddWithValue("?id", asset.ID); | 242 | "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString() |
264 | cmd.Parameters.AddWithValue("?access_time", now); | 243 | + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name); |
265 | cmd.ExecuteNonQuery(); | ||
266 | cmd.Dispose(); | ||
267 | } | 244 | } |
268 | } | 245 | } |
269 | catch (Exception e) | ||
270 | { | ||
271 | m_log.ErrorFormat( | ||
272 | "[ASSETS DB]: " + | ||
273 | "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString() | ||
274 | + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name); | ||
275 | _dbConnection.Reconnect(); | ||
276 | } | ||
277 | } | 246 | } |
278 | 247 | ||
279 | } | 248 | } |
@@ -287,37 +256,30 @@ namespace OpenSim.Data.MySQL | |||
287 | { | 256 | { |
288 | bool assetExists = false; | 257 | bool assetExists = false; |
289 | 258 | ||
290 | lock (_dbConnection) | 259 | lock (m_dbLock) |
291 | { | 260 | { |
292 | _dbConnection.CheckConnection(); | 261 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
293 | |||
294 | MySqlCommand cmd = | ||
295 | new MySqlCommand( | ||
296 | "SELECT id FROM assets WHERE id=?id", | ||
297 | _dbConnection.Connection); | ||
298 | |||
299 | cmd.Parameters.AddWithValue("?id", uuid.ToString()); | ||
300 | |||
301 | try | ||
302 | { | 262 | { |
303 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) | 263 | dbcon.Open(); |
264 | using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon)) | ||
304 | { | 265 | { |
305 | if (dbReader.Read()) | 266 | cmd.Parameters.AddWithValue("?id", uuid.ToString()); |
267 | |||
268 | try | ||
306 | { | 269 | { |
307 | assetExists = true; | 270 | using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) |
271 | { | ||
272 | if (dbReader.Read()) | ||
273 | assetExists = true; | ||
274 | } | ||
275 | } | ||
276 | catch (Exception e) | ||
277 | { | ||
278 | m_log.ErrorFormat( | ||
279 | "[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid); | ||
308 | } | 280 | } |
309 | |||
310 | dbReader.Close(); | ||
311 | cmd.Dispose(); | ||
312 | } | 281 | } |
313 | } | 282 | } |
314 | catch (Exception e) | ||
315 | { | ||
316 | m_log.ErrorFormat( | ||
317 | "[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString() | ||
318 | + Environment.NewLine + "Attempting reconnection", uuid); | ||
319 | _dbConnection.Reconnect(); | ||
320 | } | ||
321 | } | 283 | } |
322 | 284 | ||
323 | return assetExists; | 285 | return assetExists; |
@@ -335,38 +297,39 @@ namespace OpenSim.Data.MySQL | |||
335 | { | 297 | { |
336 | List<AssetMetadata> retList = new List<AssetMetadata>(count); | 298 | List<AssetMetadata> retList = new List<AssetMetadata>(count); |
337 | 299 | ||
338 | lock (_dbConnection) | 300 | lock (m_dbLock) |
339 | { | 301 | { |
340 | _dbConnection.CheckConnection(); | 302 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) |
341 | |||
342 | MySqlCommand cmd = new MySqlCommand("SELECT name,description,assetType,temporary,id FROM assets LIMIT ?start, ?count", _dbConnection.Connection); | ||
343 | cmd.Parameters.AddWithValue("?start", start); | ||
344 | cmd.Parameters.AddWithValue("?count", count); | ||
345 | |||
346 | try | ||
347 | { | 303 | { |
348 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) | 304 | dbcon.Open(); |
305 | MySqlCommand cmd = new MySqlCommand("SELECT name,description,assetType,temporary,id FROM assets LIMIT ?start, ?count", dbcon); | ||
306 | cmd.Parameters.AddWithValue("?start", start); | ||
307 | cmd.Parameters.AddWithValue("?count", count); | ||
308 | |||
309 | try | ||
349 | { | 310 | { |
350 | while (dbReader.Read()) | 311 | using (MySqlDataReader dbReader = cmd.ExecuteReader()) |
351 | { | 312 | { |
352 | AssetMetadata metadata = new AssetMetadata(); | 313 | while (dbReader.Read()) |
353 | metadata.Name = (string) dbReader["name"]; | 314 | { |
354 | metadata.Description = (string) dbReader["description"]; | 315 | AssetMetadata metadata = new AssetMetadata(); |
355 | metadata.Type = (sbyte) dbReader["assetType"]; | 316 | metadata.Name = (string)dbReader["name"]; |
356 | metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct. | 317 | metadata.Description = (string)dbReader["description"]; |
357 | metadata.FullID = new UUID((string) dbReader["id"]); | 318 | metadata.Type = (sbyte)dbReader["assetType"]; |
358 | 319 | metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct. | |
359 | // Current SHA1s are not stored/computed. | 320 | metadata.FullID = new UUID((string)dbReader["id"]); |
360 | metadata.SHA1 = new byte[] {}; | 321 | |
361 | 322 | // Current SHA1s are not stored/computed. | |
362 | retList.Add(metadata); | 323 | metadata.SHA1 = new byte[] { }; |
324 | |||
325 | retList.Add(metadata); | ||
326 | } | ||
363 | } | 327 | } |
364 | } | 328 | } |
365 | } | 329 | catch (Exception e) |
366 | catch (Exception e) | 330 | { |
367 | { | 331 | m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString()); |
368 | m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString() + Environment.NewLine + "Attempting reconnection"); | 332 | } |
369 | _dbConnection.Reconnect(); | ||
370 | } | 333 | } |
371 | } | 334 | } |
372 | 335 | ||
@@ -374,7 +337,5 @@ namespace OpenSim.Data.MySQL | |||
374 | } | 337 | } |
375 | 338 | ||
376 | #endregion | 339 | #endregion |
377 | |||
378 | |||
379 | } | 340 | } |
380 | } | 341 | } |