aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL/MySQLFSAssetData.cs
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Data/MySQL/MySQLFSAssetData.cs
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Data/MySQL/MySQLFSAssetData.cs')
-rw-r--r--OpenSim/Data/MySQL/MySQLFSAssetData.cs414
1 files changed, 414 insertions, 0 deletions
diff --git a/OpenSim/Data/MySQL/MySQLFSAssetData.cs b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
new file mode 100644
index 0000000..19e23b5
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
@@ -0,0 +1,414 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using System.Data;
32using OpenSim.Framework;
33using OpenSim.Framework.Console;
34using log4net;
35using MySql.Data.MySqlClient;
36using OpenMetaverse;
37
38namespace OpenSim.Data.MySQL
39{
40 public class MySQLFSAssetData : IFSAssetDataPlugin
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 protected MySqlConnection m_Connection = null;
45 protected string m_ConnectionString;
46 protected string m_Table;
47 protected Object m_connLock = new Object();
48
49 /// <summary>
50 /// Number of days that must pass before we update the access time on an asset when it has been fetched
51 /// Config option to change this is "DaysBetweenAccessTimeUpdates"
52 /// </summary>
53 private int DaysBetweenAccessTimeUpdates = 0;
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 public MySQLFSAssetData()
61 {
62 }
63
64 #region IPlugin Members
65
66 public string Version { get { return "1.0.0.0"; } }
67
68 // Loads and initialises the MySQL storage plugin and checks for migrations
69 public void Initialise(string connect, string realm, int UpdateAccessTime)
70 {
71 m_ConnectionString = connect;
72 m_Table = realm;
73
74 DaysBetweenAccessTimeUpdates = UpdateAccessTime;
75
76 try
77 {
78 OpenDatabase();
79
80 Migration m = new Migration(m_Connection, Assembly, "FSAssetStore");
81 m.Update();
82 }
83 catch (MySqlException e)
84 {
85 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}", e.Message.ToString());
86 }
87 }
88
89 public void Initialise()
90 {
91 throw new NotImplementedException();
92 }
93
94 public void Dispose() { }
95
96 public string Name
97 {
98 get { return "MySQL FSAsset storage engine"; }
99 }
100
101 #endregion
102
103 private bool OpenDatabase()
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 {
136 lock (m_connLock)
137 {
138 bool errorSeen = false;
139
140 while (true)
141 {
142 try
143 {
144 c.ExecuteNonQuery();
145 }
146 catch (MySqlException)
147 {
148 System.Threading.Thread.Sleep(500);
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
164 break;
165 }
166 }
167 }
168
169 #region IFSAssetDataPlugin Members
170
171 public AssetMetadata Get(string id, out string hash)
172 {
173 hash = String.Empty;
174
175 MySqlCommand cmd = new MySqlCommand();
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
182 if (!reader.Read())
183 {
184 reader.Close();
185 FreeCommand(cmd);
186 return null;
187 }
188
189 AssetMetadata meta = new AssetMetadata();
190
191 hash = reader["hash"].ToString();
192
193 meta.ID = id;
194 meta.FullID = new UUID(id);
195
196 meta.Name = reader["name"].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
203 int AccessTime = Convert.ToInt32(reader["access_time"]);
204
205 reader.Close();
206
207 UpdateAccessTime(AccessTime, cmd);
208
209 FreeCommand(cmd);
210
211 return meta;
212 }
213
214 private void UpdateAccessTime(int AccessTime, MySqlCommand cmd)
215 {
216 // Reduce DB work by only updating access time if asset hasn't recently been accessed
217 // 0 By Default, Config option is "DaysBetweenAccessTimeUpdates"
218 if (DaysBetweenAccessTimeUpdates > 0 && (DateTime.UtcNow - Utils.UnixTimeToDateTime(AccessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
219 return;
220
221 cmd.CommandText = String.Format("UPDATE {0} SET `access_time` = UNIX_TIMESTAMP() WHERE `id` = ?id", m_Table);
222
223 cmd.ExecuteNonQuery();
224 }
225
226 protected void FreeCommand(MySqlCommand cmd)
227 {
228 MySqlConnection c = cmd.Connection;
229 cmd.Dispose();
230 c.Close();
231 c.Dispose();
232 }
233
234 public bool Store(AssetMetadata meta, string hash)
235 {
236 try
237 {
238 string oldhash;
239 AssetMetadata existingAsset = Get(meta.ID, out oldhash);
240
241 MySqlCommand cmd = m_Connection.CreateCommand();
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 {
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);
253
254 ExecuteNonQuery(cmd);
255
256 cmd.Dispose();
257
258 return true;
259 }
260
261 //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table);
262
263 //ExecuteNonQuery(cmd);
264
265 cmd.Dispose();
266 return false;
267 }
268 catch(Exception e)
269 {
270 m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID);
271 m_log.Error(e.ToString());
272 return false;
273 }
274 }
275
276 /// <summary>
277 /// Check if the assets exist in the database.
278 /// </summary>
279 /// <param name="uuids">The asset UUID's</param>
280 /// <returns>For each asset: true if it exists, false otherwise</returns>
281 public bool[] AssetsExist(UUID[] uuids)
282 {
283 if (uuids.Length == 0)
284 return new bool[0];
285
286 HashSet<UUID> exists = new HashSet<UUID>();
287
288 string ids = "'" + string.Join("','", uuids) + "'";
289 string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table);
290
291 using (MySqlCommand cmd = m_Connection.CreateCommand())
292 {
293 cmd.CommandText = sql;
294
295 using (MySqlDataReader dbReader = cmd.ExecuteReader())
296 {
297 while (dbReader.Read())
298 {
299 UUID id = DBGuid.FromDB(dbReader["ID"]);
300 exists.Add(id);
301 }
302 }
303 }
304
305 bool[] results = new bool[uuids.Length];
306 for (int i = 0; i < uuids.Length; i++)
307 results[i] = exists.Contains(uuids[i]);
308 return results;
309 }
310
311 public int Count()
312 {
313 MySqlCommand cmd = m_Connection.CreateCommand();
314
315 cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table);
316
317 IDataReader reader = ExecuteReader(cmd);
318
319 reader.Read();
320
321 int count = Convert.ToInt32(reader["count"]);
322
323 reader.Close();
324 FreeCommand(cmd);
325
326 return count;
327 }
328
329 public bool Delete(string id)
330 {
331 using (MySqlCommand cmd = m_Connection.CreateCommand())
332 {
333 cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table);
334
335 cmd.Parameters.AddWithValue("?id", id);
336
337 ExecuteNonQuery(cmd);
338 }
339
340 return true;
341 }
342
343 public void Import(string conn, string table, int start, int count, bool force, FSStoreDelegate store)
344 {
345 MySqlConnection importConn;
346
347 try
348 {
349 importConn = new MySqlConnection(conn);
350
351 importConn.Open();
352 }
353 catch (MySqlException e)
354 {
355 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}",
356 e.Message.ToString());
357
358 return;
359 }
360
361 int imported = 0;
362
363 MySqlCommand cmd = importConn.CreateCommand();
364
365 string limit = String.Empty;
366 if (count != -1)
367 {
368 limit = String.Format(" limit {0},{1}", start, count);
369 }
370
371 cmd.CommandText = String.Format("select * from {0}{1}", table, limit);
372
373 MainConsole.Instance.Output("Querying database");
374 IDataReader reader = cmd.ExecuteReader();
375
376 MainConsole.Instance.Output("Reading data");
377
378 while (reader.Read())
379 {
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
388 meta.ID = reader["id"].ToString();
389 meta.FullID = new UUID(meta.ID);
390
391 meta.Name = reader["name"].ToString();
392 meta.Description = reader["description"].ToString();
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
397 asset.Metadata = meta;
398 asset.Data = (byte[])reader["data"];
399
400 store(asset, force);
401
402 imported++;
403 }
404
405 reader.Close();
406 cmd.Dispose();
407 importConn.Close();
408
409 MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported));
410 }
411
412 #endregion
413 }
414}