clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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.Data.SqlClient;
31 using System.Reflection;
32 using System.Collections.Generic;
33 using OpenMetaverse;
34 using log4net;
35 using OpenSim.Framework;
36  
37 namespace OpenSim.Data.MSSQL
38 {
39 /// <summary>
40 /// A MSSQL Interface for the Asset server
41 /// </summary>
42 public class MSSQLAssetData : AssetDataBase
43 {
44 private const string _migrationStore = "AssetStore";
45  
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private long m_ticksToEpoch;
48 /// <summary>
49 /// Database manager
50 /// </summary>
51 private MSSQLManager m_database;
52 private string m_connectionString;
53  
54 #region IPlugin Members
55  
56 override public void Dispose() { }
57  
58 /// <summary>
59 /// <para>Initialises asset interface</para>
60 /// </summary>
61 // [Obsolete("Cannot be default-initialized!")]
62 override public void Initialise()
63 {
64 m_log.Info("[MSSQLAssetData]: " + Name + " cannot be default-initialized!");
65 throw new PluginNotInitialisedException(Name);
66 }
67  
68 /// <summary>
69 /// Initialises asset interface
70 /// </summary>
71 /// <para>
72 /// a string instead of file, if someone writes the support
73 /// </para>
74 /// <param name="connectionString">connect string</param>
75 override public void Initialise(string connectionString)
76 {
77 m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
78  
79 m_database = new MSSQLManager(connectionString);
80 m_connectionString = connectionString;
81  
82 //New migration to check for DB changes
83 m_database.CheckMigration(_migrationStore);
84 }
85  
86 /// <summary>
87 /// Database provider version.
88 /// </summary>
89 override public string Version
90 {
91 get { return m_database.getVersion(); }
92 }
93  
94 /// <summary>
95 /// The name of this DB provider.
96 /// </summary>
97 override public string Name
98 {
99 get { return "MSSQL Asset storage engine"; }
100 }
101  
102 #endregion
103  
104 #region IAssetDataPlugin Members
105  
106 /// <summary>
107 /// Fetch Asset from m_database
108 /// </summary>
109 /// <param name="assetID">the asset UUID</param>
110 /// <returns></returns>
111 override public AssetBase GetAsset(UUID assetID)
112 {
113 string sql = "SELECT * FROM assets WHERE id = @id";
114 using (SqlConnection conn = new SqlConnection(m_connectionString))
115 using (SqlCommand cmd = new SqlCommand(sql, conn))
116 {
117 cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
118 conn.Open();
119 using (SqlDataReader reader = cmd.ExecuteReader())
120 {
121 if (reader.Read())
122 {
123 AssetBase asset = new AssetBase(
124 DBGuid.FromDB(reader["id"]),
125 (string)reader["name"],
126 Convert.ToSByte(reader["assetType"]),
127 reader["creatorid"].ToString()
128 );
129 // Region Main
130 asset.Description = (string)reader["description"];
131 asset.Local = Convert.ToBoolean(reader["local"]);
132 asset.Temporary = Convert.ToBoolean(reader["temporary"]);
133 asset.Flags = (AssetFlags)(Convert.ToInt32(reader["asset_flags"]));
134 asset.Data = (byte[])reader["data"];
135 return asset;
136 }
137 return null; // throw new Exception("No rows to return");
138 }
139 }
140 }
141  
142 /// <summary>
143 /// Create asset in m_database
144 /// </summary>
145 /// <param name="asset">the asset</param>
146 override public void StoreAsset(AssetBase asset)
147 {
148  
149 string sql =
150 @"IF EXISTS(SELECT * FROM assets WHERE id=@id)
151 UPDATE assets set name = @name, description = @description, assetType = @assetType,
152 local = @local, temporary = @temporary, creatorid = @creatorid, data = @data
153 WHERE id=@id
154 ELSE
155 INSERT INTO assets
156 ([id], [name], [description], [assetType], [local],
157 [temporary], [create_time], [access_time], [creatorid], [asset_flags], [data])
158 VALUES
159 (@id, @name, @description, @assetType, @local,
160 @temporary, @create_time, @access_time, @creatorid, @asset_flags, @data)";
161  
162 string assetName = asset.Name;
163 if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
164 {
165 assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
166 m_log.WarnFormat(
167 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
168 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
169 }
170  
171 string assetDescription = asset.Description;
172 if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
173 {
174 assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
175 m_log.WarnFormat(
176 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
177 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
178 }
179  
180 using (SqlConnection conn = new SqlConnection(m_connectionString))
181 using (SqlCommand command = new SqlCommand(sql, conn))
182 {
183 int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
184 command.Parameters.Add(m_database.CreateParameter("id", asset.FullID));
185 command.Parameters.Add(m_database.CreateParameter("name", assetName));
186 command.Parameters.Add(m_database.CreateParameter("description", assetDescription));
187 command.Parameters.Add(m_database.CreateParameter("assetType", asset.Type));
188 command.Parameters.Add(m_database.CreateParameter("local", asset.Local));
189 command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary));
190 command.Parameters.Add(m_database.CreateParameter("access_time", now));
191 command.Parameters.Add(m_database.CreateParameter("create_time", now));
192 command.Parameters.Add(m_database.CreateParameter("asset_flags", (int)asset.Flags));
193 command.Parameters.Add(m_database.CreateParameter("creatorid", asset.Metadata.CreatorID));
194 command.Parameters.Add(m_database.CreateParameter("data", asset.Data));
195 conn.Open();
196 try
197 {
198 command.ExecuteNonQuery();
199 }
200 catch(Exception e)
201 {
202 m_log.Error("[ASSET DB]: Error storing item :" + e.Message);
203 }
204 }
205 }
206  
207  
208 // Commented out since currently unused - this probably should be called in GetAsset()
209 // private void UpdateAccessTime(AssetBase asset)
210 // {
211 // using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = @access_time WHERE id=@id"))
212 // {
213 // int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
214 // cmd.Parameters.AddWithValue("@id", asset.FullID.ToString());
215 // cmd.Parameters.AddWithValue("@access_time", now);
216 // try
217 // {
218 // cmd.ExecuteNonQuery();
219 // }
220 // catch (Exception e)
221 // {
222 // m_log.Error(e.ToString());
223 // }
224 // }
225 // }
226  
227 /// <summary>
228 /// Check if the assets exist in the database.
229 /// </summary>
230 /// <param name="uuids">The assets' IDs</param>
231 /// <returns>For each asset: true if it exists, false otherwise</returns>
232 public override bool[] AssetsExist(UUID[] uuids)
233 {
234 if (uuids.Length == 0)
235 return new bool[0];
236  
237 HashSet<UUID> exist = new HashSet<UUID>();
238  
239 string ids = "'" + string.Join("','", uuids) + "'";
240 string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
241  
242 using (SqlConnection conn = new SqlConnection(m_connectionString))
243 using (SqlCommand cmd = new SqlCommand(sql, conn))
244 {
245 conn.Open();
246 using (SqlDataReader reader = cmd.ExecuteReader())
247 {
248 while (reader.Read())
249 {
250 UUID id = DBGuid.FromDB(reader["id"]);
251 exist.Add(id);
252 }
253 }
254 }
255  
256 bool[] results = new bool[uuids.Length];
257 for (int i = 0; i < uuids.Length; i++)
258 results[i] = exist.Contains(uuids[i]);
259 return results;
260 }
261  
262 /// <summary>
263 /// Returns a list of AssetMetadata objects. The list is a subset of
264 /// the entire data set offset by <paramref name="start" /> containing
265 /// <paramref name="count" /> elements.
266 /// </summary>
267 /// <param name="start">The number of results to discard from the total data set.</param>
268 /// <param name="count">The number of rows the returned list should contain.</param>
269 /// <returns>A list of AssetMetadata objects.</returns>
270 public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
271 {
272 List<AssetMetadata> retList = new List<AssetMetadata>(count);
273 string sql = @"WITH OrderedAssets AS
274 (
275 SELECT id, name, description, assetType, temporary, creatorid,
276 RowNumber = ROW_NUMBER() OVER (ORDER BY id)
277 FROM assets
278 )
279 SELECT *
280 FROM OrderedAssets
281 WHERE RowNumber BETWEEN @start AND @stop;";
282  
283 using (SqlConnection conn = new SqlConnection(m_connectionString))
284 using (SqlCommand cmd = new SqlCommand(sql, conn))
285 {
286 cmd.Parameters.Add(m_database.CreateParameter("start", start));
287 cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
288 conn.Open();
289 using (SqlDataReader reader = cmd.ExecuteReader())
290 {
291 while (reader.Read())
292 {
293 AssetMetadata metadata = new AssetMetadata();
294 metadata.FullID = DBGuid.FromDB(reader["id"]);
295 metadata.Name = (string)reader["name"];
296 metadata.Description = (string)reader["description"];
297 metadata.Type = Convert.ToSByte(reader["assetType"]);
298 metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
299 metadata.CreatorID = (string)reader["creatorid"];
300 retList.Add(metadata);
301 }
302 }
303 }
304  
305 return retList;
306 }
307  
308 public override bool Delete(string id)
309 {
310 return false;
311 }
312 #endregion
313 }
314 }