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