OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
PGSQLAssetData.cs
Go to the documentation of this file.
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 {
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;
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 
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 
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 
95  override public string Version
96  {
97  get { return m_database.getVersion(); }
98  }
99 
103  override public string Name
104  {
105  get { return "PGSQL Asset storage engine"; }
106  }
107 
108  #endregion
109 
110  #region IAssetDataPlugin Members
111 
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 
152  override public bool 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  return true;
212  }
213 
214 
215 // Commented out since currently unused - this probably should be called in GetAsset()
216 // private void UpdateAccessTime(AssetBase asset)
217 // {
218 // using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = :access_time WHERE id=:id"))
219 // {
220 // int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
221 // cmd.Parameters.AddWithValue(":id", asset.FullID.ToString());
222 // cmd.Parameters.AddWithValue(":access_time", now);
223 // try
224 // {
225 // cmd.ExecuteNonQuery();
226 // }
227 // catch (Exception e)
228 // {
229 // m_log.Error(e.ToString());
230 // }
231 // }
232 // }
233 
239  public override bool[] AssetsExist(UUID[] uuids)
240  {
241  if (uuids.Length == 0)
242  return new bool[0];
243 
244  HashSet<UUID> exist = new HashSet<UUID>();
245 
246  string ids = "'" + string.Join("','", uuids) + "'";
247  string sql = string.Format("SELECT id FROM assets WHERE id IN ({0})", ids);
248 
249  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
250  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
251  {
252  conn.Open();
253  using (NpgsqlDataReader reader = cmd.ExecuteReader())
254  {
255  while (reader.Read())
256  {
257  UUID id = DBGuid.FromDB(reader["id"]);
258  exist.Add(id);
259  }
260  }
261  }
262 
263  bool[] results = new bool[uuids.Length];
264  for (int i = 0; i < uuids.Length; i++)
265  results[i] = exist.Contains(uuids[i]);
266  return results;
267  }
268 
277  public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
278  {
279  List<AssetMetadata> retList = new List<AssetMetadata>(count);
280  string sql = @" SELECT id, name, description, " + "\"assetType\"" + @", temporary, creatorid
281  FROM assets
282  order by id
283  limit :stop
284  offset :start;";
285 
286  using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
287  using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
288  {
289  cmd.Parameters.Add(m_database.CreateParameter("start", start));
290  cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
291  conn.Open();
292  using (NpgsqlDataReader reader = cmd.ExecuteReader())
293  {
294  while (reader.Read())
295  {
296  AssetMetadata metadata = new AssetMetadata();
297  metadata.FullID = DBGuid.FromDB(reader["id"]);
298  metadata.Name = (string)reader["name"];
299  metadata.Description = (string)reader["description"];
300  metadata.Type = Convert.ToSByte(reader["assetType"]);
301  metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
302  metadata.CreatorID = (string)reader["creatorid"];
303  retList.Add(metadata);
304  }
305  }
306  }
307 
308  return retList;
309  }
310 
311  public override bool Delete(string id)
312  {
313  return false;
314  }
315  #endregion
316  }
317 }
override void Initialise(string connectionString)
Initialises asset interface
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
A PGSQL Interface for the Asset server
A management class for the MS SQL Storage Engine
Definition: PGSQLManager.cs:44
static readonly int MAX_ASSET_NAME
Definition: AssetBase.cs:53
override bool StoreAsset(AssetBase asset)
Create asset in m_database
static readonly int MAX_ASSET_DESC
Definition: AssetBase.cs:54
Exception thrown if Initialise has been called, but failed.
Definition: IPlugin.cs:35
override bool Delete(string id)
override AssetBase GetAsset(UUID assetID)
Fetch Asset from m_database
override bool[] AssetsExist(UUID[] uuids)
Check if the assets exist in the database.
override List< AssetMetadata > FetchAssetMetadataSet(int start, int count)
Returns a list of AssetMetadata objects. The list is a subset of the entire data set offset by start ...