aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Data/MySQL')
-rw-r--r--OpenSim/Data/MySQL/MySQLFSAssetData.cs361
1 files changed, 361 insertions, 0 deletions
diff --git a/OpenSim/Data/MySQL/MySQLFSAssetData.cs b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
new file mode 100644
index 0000000..a57bfe0
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLFSAssetData.cs
@@ -0,0 +1,361 @@
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.Data;
33using OpenSim.Framework;
34using OpenSim.Framework.Console;
35using OpenSim.Server.Base;
36using OpenSim.Services.Base;
37using OpenSim.Services.Interfaces;
38using Nini.Config;
39using log4net;
40using MySql.Data.MySqlClient;
41using System.Data;
42using OpenMetaverse;
43
44namespace OpenSim.Data.MySQL
45{
46 public delegate string StoreDelegate(AssetBase asset, bool force);
47
48 public class FSAssetConnectorData
49 {
50 private static readonly ILog m_log =
51 LogManager.GetLogger(
52 MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected MySqlConnection m_Connection = null;
55 protected string m_ConnectionString;
56 protected string m_Table;
57 protected Object m_connLock = new Object();
58
59 public FSAssetConnectorData(string connectionString, string table)
60 {
61 m_ConnectionString = connectionString;
62 m_Table = table;
63
64 OpenDatabase();
65 }
66
67 private bool OpenDatabase()
68 {
69 try
70 {
71 m_Connection = new MySqlConnection(m_ConnectionString);
72
73 m_Connection.Open();
74 }
75 catch (MySqlException e)
76 {
77 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}",
78 e.Message.ToString());
79
80 return false;
81 }
82
83 return true;
84 }
85
86 private IDataReader ExecuteReader(MySqlCommand c)
87 {
88 IDataReader r = null;
89 MySqlConnection connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
90 connection.Open();
91 c.Connection = connection;
92
93 r = c.ExecuteReader();
94
95 return r;
96 }
97
98 private void ExecuteNonQuery(MySqlCommand c)
99 {
100 lock (m_connLock)
101 {
102 bool errorSeen = false;
103
104 while (true)
105 {
106 try
107 {
108 c.ExecuteNonQuery();
109 }
110 catch (MySqlException)
111 {
112 System.Threading.Thread.Sleep(500);
113
114 m_Connection.Close();
115 m_Connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
116 m_Connection.Open();
117 c.Connection = m_Connection;
118
119 if (!errorSeen)
120 {
121 errorSeen = true;
122 continue;
123 }
124 m_log.ErrorFormat("[FSASSETS] MySQL command: {0}", c.CommandText);
125 throw;
126 }
127
128 break;
129 }
130 }
131 }
132
133 public AssetMetadata Get(string id, out string hash)
134 {
135 hash = String.Empty;
136
137 MySqlCommand cmd = new MySqlCommand();
138
139 cmd.CommandText = String.Format("select id, name, description, type, hash, create_time, asset_flags from {0} where id = ?id", m_Table);
140 cmd.Parameters.AddWithValue("?id", id);
141
142 IDataReader reader = ExecuteReader(cmd);
143
144 if (!reader.Read())
145 {
146 reader.Close();
147 FreeCommand(cmd);
148 return null;
149 }
150
151 AssetMetadata meta = new AssetMetadata();
152
153 hash = reader["hash"].ToString();
154
155 meta.ID = id;
156 meta.FullID = new UUID(id);
157
158 meta.Name = reader["name"].ToString();
159 meta.Description = reader["description"].ToString();
160 meta.Type = (sbyte)Convert.ToInt32(reader["type"]);
161 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
162 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
163 meta.Flags = (AssetFlags)Convert.ToInt32(reader["asset_flags"]);
164
165 reader.Close();
166
167 cmd.CommandText = String.Format("update {0} set access_time = UNIX_TIMESTAMP() where id = ?id", m_Table);
168
169 cmd.ExecuteNonQuery();
170
171 FreeCommand(cmd);
172
173 return meta;
174 }
175
176 protected void FreeCommand(MySqlCommand cmd)
177 {
178 MySqlConnection c = cmd.Connection;
179 cmd.Dispose();
180 c.Close();
181 c.Dispose();
182 }
183
184 public bool Store(AssetMetadata meta, string hash)
185 {
186 try
187 {
188 string oldhash;
189 AssetMetadata existingAsset = Get(meta.ID, out oldhash);
190
191 MySqlCommand cmd = m_Connection.CreateCommand();
192
193 cmd.Parameters.AddWithValue("?id", meta.ID);
194 cmd.Parameters.AddWithValue("?name", meta.Name);
195 cmd.Parameters.AddWithValue("?description", meta.Description);
196 cmd.Parameters.AddWithValue("?type", meta.Type.ToString());
197 cmd.Parameters.AddWithValue("?hash", hash);
198 cmd.Parameters.AddWithValue("?asset_flags", meta.Flags);
199
200 if (existingAsset == null)
201 {
202 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);
203
204 ExecuteNonQuery(cmd);
205
206 cmd.Dispose();
207
208 return true;
209 }
210
211 //cmd.CommandText = String.Format("update {0} set hash = ?hash, access_time = UNIX_TIMESTAMP() where id = ?id", m_Table);
212
213 //ExecuteNonQuery(cmd);
214
215 cmd.Dispose();
216 return false;
217 }
218 catch(Exception e)
219 {
220 m_log.Error("[FSAssets] Failed to store asset with ID " + meta.ID);
221 m_log.Error(e.ToString());
222 return false;
223 }
224 }
225
226 /// <summary>
227 /// Check if the assets exist in the database.
228 /// </summary>
229 /// <param name="uuids">The asset UUID's</param>
230 /// <returns>For each asset: true if it exists, false otherwise</returns>
231 public bool[] AssetsExist(UUID[] uuids)
232 {
233 if (uuids.Length == 0)
234 return new bool[0];
235
236 HashSet<UUID> exists = new HashSet<UUID>();
237
238 string ids = "'" + string.Join("','", uuids) + "'";
239 string sql = string.Format("select id from {1} where id in ({0})", ids, m_Table);
240
241 using (MySqlCommand cmd = m_Connection.CreateCommand())
242 {
243 cmd.CommandText = sql;
244
245 using (MySqlDataReader dbReader = cmd.ExecuteReader())
246 {
247 while (dbReader.Read())
248 {
249 UUID id = DBGuid.FromDB(dbReader["ID"]);
250 exists.Add(id);
251 }
252 }
253 }
254
255 bool[] results = new bool[uuids.Length];
256 for (int i = 0; i < uuids.Length; i++)
257 results[i] = exists.Contains(uuids[i]);
258 return results;
259 }
260
261 public int Count()
262 {
263 MySqlCommand cmd = m_Connection.CreateCommand();
264
265 cmd.CommandText = String.Format("select count(*) as count from {0}", m_Table);
266
267 IDataReader reader = ExecuteReader(cmd);
268
269 reader.Read();
270
271 int count = Convert.ToInt32(reader["count"]);
272
273 reader.Close();
274 FreeCommand(cmd);
275
276 return count;
277 }
278
279 public void Delete(string id)
280 {
281 MySqlCommand cmd = m_Connection.CreateCommand();
282
283 cmd.CommandText = String.Format("delete from {0} where id = ?id", m_Table);
284
285 cmd.Parameters.AddWithValue("?id", id);
286
287 ExecuteNonQuery(cmd);
288
289 cmd.Dispose();
290 }
291
292 public void Import(string conn, string table, int start, int count, bool force, StoreDelegate store)
293 {
294 MySqlConnection importConn;
295
296 try
297 {
298 importConn = new MySqlConnection(conn);
299
300 importConn.Open();
301 }
302 catch (MySqlException e)
303 {
304 m_log.ErrorFormat("[FSASSETS]: Can't connect to database: {0}",
305 e.Message.ToString());
306
307 return;
308 }
309
310 int imported = 0;
311
312 MySqlCommand cmd = importConn.CreateCommand();
313
314 string limit = String.Empty;
315 if (count != -1)
316 {
317 limit = String.Format(" limit {0},{1}", start, count);
318 }
319
320 cmd.CommandText = String.Format("select * from {0}{1}", table, limit);
321
322 MainConsole.Instance.Output("Querying database");
323 IDataReader reader = cmd.ExecuteReader();
324
325 MainConsole.Instance.Output("Reading data");
326
327 while (reader.Read())
328 {
329 if ((imported % 100) == 0)
330 {
331 MainConsole.Instance.Output(String.Format("{0} assets imported so far", imported));
332 }
333
334 AssetBase asset = new AssetBase();
335 AssetMetadata meta = new AssetMetadata();
336
337 meta.ID = reader["id"].ToString();
338 meta.FullID = new UUID(meta.ID);
339
340 meta.Name = reader["name"].ToString();
341 meta.Description = reader["description"].ToString();
342 meta.Type = (sbyte)Convert.ToInt32(reader["assetType"]);
343 meta.ContentType = SLUtil.SLAssetTypeToContentType(meta.Type);
344 meta.CreationDate = Util.ToDateTime(Convert.ToInt32(reader["create_time"]));
345
346 asset.Metadata = meta;
347 asset.Data = (byte[])reader["data"];
348
349 store(asset, force);
350
351 imported++;
352 }
353
354 reader.Close();
355 cmd.Dispose();
356 importConn.Close();
357
358 MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported));
359 }
360 }
361}