opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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  
28 using System;
29 using System.Data;
30 using System.Reflection;
31 using System.Collections.Generic;
32 using log4net;
33 using MySql.Data.MySqlClient;
34 using OpenMetaverse;
35 using OpenSim.Framework;
36 using OpenSim.Data;
37  
38 namespace OpenSim.Data.MySQL
39 {
40 /// <summary>
41 /// A MySQL Interface for the Asset Server
42 /// </summary>
43 public class MySQLAssetData : AssetDataBase
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46  
47 private string m_connectionString;
48 private object m_dbLock = new object();
49  
50 protected virtual Assembly Assembly
51 {
52 get { return GetType().Assembly; }
53 }
54  
55 #region IPlugin Members
56  
57 public override string Version { get { return "1.0.0.0"; } }
58  
59 /// <summary>
60 /// <para>Initialises Asset interface</para>
61 /// <para>
62 /// <list type="bullet">
63 /// <item>Loads and initialises the MySQL storage plugin.</item>
64 /// <item>Warns and uses the obsolete mysql_connection.ini if connect string is empty.</item>
65 /// <item>Check for migration</item>
66 /// </list>
67 /// </para>
68 /// </summary>
69 /// <param name="connect">connect string</param>
70 public override void Initialise(string connect)
71 {
72 m_connectionString = connect;
73  
74 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
75 {
76 dbcon.Open();
77 Migration m = new Migration(dbcon, Assembly, "AssetStore");
78 m.Update();
79 }
80 }
81  
82 public override void Initialise()
83 {
84 throw new NotImplementedException();
85 }
86  
87 public override void Dispose() { }
88  
89 /// <summary>
90 /// The name of this DB provider
91 /// </summary>
92 override public string Name
93 {
94 get { return "MySQL Asset storage engine"; }
95 }
96  
97 #endregion
98  
99 #region IAssetDataPlugin Members
100  
101 /// <summary>
102 /// Fetch Asset <paramref name="assetID"/> from database
103 /// </summary>
104 /// <param name="assetID">Asset UUID to fetch</param>
105 /// <returns>Return the asset</returns>
106 /// <remarks>On failure : throw an exception and attempt to reconnect to database</remarks>
107 override public AssetBase GetAsset(UUID assetID)
108 {
109 AssetBase asset = null;
110 lock (m_dbLock)
111 {
112 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
113 {
114 dbcon.Open();
115  
116 using (MySqlCommand cmd = new MySqlCommand(
117 "SELECT name, description, assetType, local, temporary, asset_flags, CreatorID, data FROM assets WHERE id=?id",
118 dbcon))
119 {
120 cmd.Parameters.AddWithValue("?id", assetID.ToString());
121  
122 try
123 {
124 using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
125 {
126 if (dbReader.Read())
127 {
128 asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"], dbReader["CreatorID"].ToString());
129 asset.Data = (byte[])dbReader["data"];
130 asset.Description = (string)dbReader["description"];
131  
132 string local = dbReader["local"].ToString();
133 if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
134 asset.Local = true;
135 else
136 asset.Local = false;
137  
138 asset.Temporary = Convert.ToBoolean(dbReader["temporary"]);
139 asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
140 }
141 }
142 }
143 catch (Exception e)
144 {
145 m_log.Error(
146 string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
147 }
148 }
149 }
150 }
151 return asset;
152 }
153  
154 /// <summary>
155 /// Create an asset in database, or update it if existing.
156 /// </summary>
157 /// <param name="asset">Asset UUID to create</param>
158 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
159 override public void StoreAsset(AssetBase asset)
160 {
161 lock (m_dbLock)
162 {
163 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
164 {
165 dbcon.Open();
166  
167 using (MySqlCommand cmd =
168 new MySqlCommand(
169 "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, asset_flags, CreatorID, data)" +
170 "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?CreatorID, ?data)",
171 dbcon))
172 {
173 string assetName = asset.Name;
174 if (asset.Name.Length > 64)
175 {
176 assetName = asset.Name.Substring(0, 64);
177 m_log.WarnFormat(
178 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
179 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
180 }
181  
182 string assetDescription = asset.Description;
183 if (asset.Description.Length > 64)
184 {
185 assetDescription = asset.Description.Substring(0, 64);
186 m_log.WarnFormat(
187 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
188 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
189 }
190  
191 try
192 {
193 using (cmd)
194 {
195 // create unix epoch time
196 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
197 cmd.Parameters.AddWithValue("?id", asset.ID);
198 cmd.Parameters.AddWithValue("?name", assetName);
199 cmd.Parameters.AddWithValue("?description", assetDescription);
200 cmd.Parameters.AddWithValue("?assetType", asset.Type);
201 cmd.Parameters.AddWithValue("?local", asset.Local);
202 cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
203 cmd.Parameters.AddWithValue("?create_time", now);
204 cmd.Parameters.AddWithValue("?access_time", now);
205 cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID);
206 cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags);
207 cmd.Parameters.AddWithValue("?data", asset.Data);
208 cmd.ExecuteNonQuery();
209 }
210 }
211 catch (Exception e)
212 {
213 m_log.Error(
214 string.Format(
215 "[ASSET DB]: MySQL failure creating asset {0} with name {1}. Exception ",
216 asset.FullID, asset.Name)
217 , e);
218 }
219 }
220 }
221 }
222 }
223  
224 private void UpdateAccessTime(AssetBase asset)
225 {
226 lock (m_dbLock)
227 {
228 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
229 {
230 dbcon.Open();
231  
232 using (MySqlCommand cmd
233 = new MySqlCommand("update assets set access_time=?access_time where id=?id", dbcon))
234 {
235 try
236 {
237 using (cmd)
238 {
239 // create unix epoch time
240 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
241 cmd.Parameters.AddWithValue("?id", asset.ID);
242 cmd.Parameters.AddWithValue("?access_time", now);
243 cmd.ExecuteNonQuery();
244 }
245 }
246 catch (Exception e)
247 {
248 m_log.Error(
249 string.Format(
250 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
251 asset.FullID, asset.Name),
252 e);
253 }
254 }
255 }
256 }
257 }
258  
259 /// <summary>
260 /// Check if the asset exists in the database
261 /// </summary>
262 /// <param name="uuid">The asset UUID</param>
263 /// <returns>true if it exists, false otherwise.</returns>
264 override public bool ExistsAsset(UUID uuid)
265 {
266 // m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
267  
268 bool assetExists = false;
269  
270 lock (m_dbLock)
271 {
272 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
273 {
274 dbcon.Open();
275 using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon))
276 {
277 cmd.Parameters.AddWithValue("?id", uuid.ToString());
278  
279 try
280 {
281 using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
282 {
283 if (dbReader.Read())
284 {
285 // m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
286 assetExists = true;
287 }
288 }
289 }
290 catch (Exception e)
291 {
292 m_log.Error(
293 string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
294 }
295 }
296 }
297 }
298  
299 return assetExists;
300 }
301  
302 /// <summary>
303 /// Returns a list of AssetMetadata objects. The list is a subset of
304 /// the entire data set offset by <paramref name="start" /> containing
305 /// <paramref name="count" /> elements.
306 /// </summary>
307 /// <param name="start">The number of results to discard from the total data set.</param>
308 /// <param name="count">The number of rows the returned list should contain.</param>
309 /// <returns>A list of AssetMetadata objects.</returns>
310 public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
311 {
312 List<AssetMetadata> retList = new List<AssetMetadata>(count);
313  
314 lock (m_dbLock)
315 {
316 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
317 {
318 dbcon.Open();
319  
320 using (MySqlCommand cmd
321 = new MySqlCommand(
322 "SELECT name,description,assetType,temporary,id,asset_flags,CreatorID FROM assets LIMIT ?start, ?count",
323 dbcon))
324 {
325 cmd.Parameters.AddWithValue("?start", start);
326 cmd.Parameters.AddWithValue("?count", count);
327  
328 try
329 {
330 using (MySqlDataReader dbReader = cmd.ExecuteReader())
331 {
332 while (dbReader.Read())
333 {
334 AssetMetadata metadata = new AssetMetadata();
335 metadata.Name = (string)dbReader["name"];
336 metadata.Description = (string)dbReader["description"];
337 metadata.Type = (sbyte)dbReader["assetType"];
338 metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct.
339 metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["asset_flags"]);
340 metadata.FullID = DBGuid.FromDB(dbReader["id"]);
341 metadata.CreatorID = dbReader["CreatorID"].ToString();
342  
343 // Current SHA1s are not stored/computed.
344 metadata.SHA1 = new byte[] { };
345  
346 retList.Add(metadata);
347 }
348 }
349 }
350 catch (Exception e)
351 {
352 m_log.Error(
353 string.Format(
354 "[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
355 start, count),
356 e);
357 }
358 }
359 }
360 }
361  
362 return retList;
363 }
364  
365 public override bool Delete(string id)
366 {
367 lock (m_dbLock)
368 {
369 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
370 {
371 dbcon.Open();
372  
373 using (MySqlCommand cmd = new MySqlCommand("delete from assets where id=?id", dbcon))
374 {
375 cmd.Parameters.AddWithValue("?id", id);
376 cmd.ExecuteNonQuery();
377 }
378 }
379 }
380  
381 return true;
382 }
383  
384 #endregion
385 }
386 }