SQLiteAssetData.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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 OpenSim 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 libsecondlife;
  32. using Mono.Data.SqliteClient;
  33. using OpenSim.Framework.Console;
  34. using System.Collections.Generic; // rex added
  35. namespace OpenSim.Framework.Data.SQLite
  36. {
  37. /// <summary>
  38. /// A User storage interface for the DB4o database system
  39. /// </summary>
  40. public class SQLiteAssetData : SQLiteBase, IAssetProvider
  41. {
  42. /// <summary>
  43. /// The database manager
  44. /// </summary>
  45. /// <summary>
  46. /// Artificial constructor called upon plugin load
  47. /// </summary>
  48. private const string assetSelect = "select * from assets";
  49. private DataSet ds;
  50. private SqliteDataAdapter da;
  51. public void Initialise(string dbfile, string dbname)
  52. {
  53. SqliteConnection conn = new SqliteConnection("URI=file:" + dbfile + ",version=3");
  54. TestTables(conn);
  55. ds = new DataSet();
  56. da = new SqliteDataAdapter(new SqliteCommand(assetSelect, conn));
  57. lock (ds)
  58. {
  59. ds.Tables.Add(createAssetsTable());
  60. setupAssetCommands(da, conn);
  61. try
  62. {
  63. da.Fill(ds.Tables["assets"]);
  64. }
  65. catch (Exception e)
  66. {
  67. MainLog.Instance.Verbose("SQLITE", e.ToString());
  68. }
  69. }
  70. return;
  71. }
  72. public AssetBase FetchAsset(LLUUID uuid)
  73. {
  74. AssetBase asset = new AssetBase();
  75. DataRow row = ds.Tables["assets"].Rows.Find(Util.ToRawUuidString(uuid));
  76. if (row != null)
  77. {
  78. return buildAsset(row);
  79. }
  80. else
  81. {
  82. return null;
  83. }
  84. }
  85. public void CreateAsset(AssetBase asset)
  86. {
  87. // no difference for now
  88. UpdateAsset(asset);
  89. }
  90. public void UpdateAsset(AssetBase asset)
  91. {
  92. LogAssetLoad(asset);
  93. DataTable assets = ds.Tables["assets"];
  94. lock (ds)
  95. {
  96. DataRow row = assets.Rows.Find(Util.ToRawUuidString(asset.FullID));
  97. if (row == null)
  98. {
  99. row = assets.NewRow();
  100. fillAssetRow(row, asset);
  101. assets.Rows.Add(row);
  102. }
  103. else
  104. {
  105. fillAssetRow(row, asset);
  106. }
  107. }
  108. }
  109. // rex new function for "replace assets" functionality
  110. public LLUUID ExistsAsset(sbyte type, string name)
  111. {
  112. LLUUID retVal = LLUUID.Zero;
  113. lock (ds)
  114. {
  115. string selectExp = "Type = '" + type.ToString() + "' AND Name = '" + name + "'";
  116. DataRow[] match = ds.Tables["assets"].Select(selectExp);
  117. if (match.Length > 0)
  118. {
  119. retVal = new LLUUID((String)match[0]["UUID"]);
  120. }
  121. }
  122. return retVal;
  123. }
  124. private void LogAssetLoad(AssetBase asset)
  125. {
  126. string temporary = asset.Temporary ? "Temporary" : "Stored";
  127. string local = asset.Local ? "Local" : "Remote";
  128. MainLog.Instance.Verbose("SQLITE",
  129. string.Format("Loaded {6} {5} Asset: [{0}][{3}/{4}] \"{1}\":{2} ({7} bytes)",
  130. asset.FullID, asset.Name, asset.Description, asset.Type,
  131. asset.InvType, temporary, local, asset.Data.Length));
  132. }
  133. public bool ExistsAsset(LLUUID uuid)
  134. {
  135. DataRow row = ds.Tables["assets"].Rows.Find(Util.ToRawUuidString(uuid));
  136. return (row != null);
  137. }
  138. // rex, new function
  139. public List<AssetBase> GetAssetList(int vAssetType)
  140. {
  141. List<AssetBase> retvals = new List<AssetBase>();
  142. lock (ds)
  143. {
  144. string selectExp = "InvType = '" + vAssetType.ToString() + "'";
  145. DataRow[] allAssets = ds.Tables["assets"].Select(selectExp);
  146. foreach (DataRow row in allAssets)
  147. {
  148. // Do not use buildAsset(row) because we don't want to return the asset.data - Tuco
  149. AssetBase asset = new AssetBase();
  150. asset.FullID = new LLUUID((String)row["UUID"]);
  151. asset.Name = (String)row["Name"];
  152. asset.Description = (String)row["Description"];
  153. asset.Type = Convert.ToSByte(row["Type"]);
  154. asset.InvType = Convert.ToSByte(row["InvType"]);
  155. asset.Local = Convert.ToBoolean(row["Local"]);
  156. asset.Temporary = Convert.ToBoolean(row["Temporary"]);
  157. retvals.Add(asset);
  158. }
  159. }
  160. return retvals;
  161. }
  162. public void DeleteAsset(LLUUID uuid)
  163. {
  164. lock (ds)
  165. {
  166. DataRow row = ds.Tables["assets"].Rows.Find(Util.ToRawUuidString(uuid));
  167. if (row != null)
  168. {
  169. row.Delete();
  170. }
  171. }
  172. }
  173. public void CommitAssets() // force a sync to the database
  174. {
  175. MainLog.Instance.Verbose("SQLITE", "Attempting commit");
  176. lock (ds)
  177. {
  178. da.Update(ds, "assets");
  179. ds.AcceptChanges();
  180. }
  181. }
  182. /***********************************************************************
  183. *
  184. * Database Definition Functions
  185. *
  186. * This should be db agnostic as we define them in ADO.NET terms
  187. *
  188. **********************************************************************/
  189. private DataTable createAssetsTable()
  190. {
  191. DataTable assets = new DataTable("assets");
  192. createCol(assets, "UUID", typeof (String));
  193. createCol(assets, "Name", typeof (String));
  194. createCol(assets, "Description", typeof (String));
  195. createCol(assets, "MediaURL", typeof(String));//rex mediaurl
  196. createCol(assets, "Type", typeof (Int32));
  197. createCol(assets, "InvType", typeof (Int32));
  198. createCol(assets, "Local", typeof (Boolean));
  199. createCol(assets, "Temporary", typeof (Boolean));
  200. createCol(assets, "Data", typeof (Byte[]));
  201. // Add in contraints
  202. assets.PrimaryKey = new DataColumn[] {assets.Columns["UUID"]};
  203. return assets;
  204. }
  205. /***********************************************************************
  206. *
  207. * Convert between ADO.NET <=> OpenSim Objects
  208. *
  209. * These should be database independant
  210. *
  211. **********************************************************************/
  212. private AssetBase buildAsset(DataRow row)
  213. {
  214. // TODO: this doesn't work yet because something more
  215. // interesting has to be done to actually get these values
  216. // back out. Not enough time to figure it out yet.
  217. AssetBase asset = new AssetBase();
  218. asset.FullID = new LLUUID((String) row["UUID"]);
  219. asset.Name = (String) row["Name"];
  220. asset.Description = (String) row["Description"];
  221. try
  222. {
  223. asset.MediaURL = (String) row["MediaURL"];//rex mediaurl
  224. }
  225. catch (Exception)
  226. {
  227. asset.MediaURL = ""; // fixme, the row returns null which can't be cast to string, happens with old dbs right now. - Tuco
  228. }
  229. asset.Type = Convert.ToSByte(row["Type"]);
  230. asset.InvType = Convert.ToSByte(row["InvType"]);
  231. asset.Local = Convert.ToBoolean(row["Local"]);
  232. asset.Temporary = Convert.ToBoolean(row["Temporary"]);
  233. asset.Data = (byte[]) row["Data"];
  234. return asset;
  235. }
  236. private void fillAssetRow(DataRow row, AssetBase asset)
  237. {
  238. row["UUID"] = Util.ToRawUuidString(asset.FullID);
  239. row["Name"] = asset.Name;
  240. if (asset.Description != null)
  241. {
  242. row["Description"] = asset.Description;
  243. }
  244. else
  245. {
  246. row["Description"] = " ";
  247. }
  248. if (asset.MediaURL != null) //rex mediaurl
  249. {
  250. row["MediaURL"] = asset.MediaURL;
  251. }
  252. else
  253. {
  254. row["MediaURL"] = " ";
  255. }
  256. row["Type"] = asset.Type;
  257. row["InvType"] = asset.InvType;
  258. row["Local"] = asset.Local;
  259. row["Temporary"] = asset.Temporary;
  260. row["Data"] = asset.Data;
  261. // ADO.NET doesn't handle NULL very well
  262. foreach (DataColumn col in ds.Tables["assets"].Columns)
  263. {
  264. if (row[col] == null)
  265. {
  266. row[col] = "";
  267. }
  268. }
  269. }
  270. /***********************************************************************
  271. *
  272. * Database Binding functions
  273. *
  274. * These will be db specific due to typing, and minor differences
  275. * in databases.
  276. *
  277. **********************************************************************/
  278. private void setupAssetCommands(SqliteDataAdapter da, SqliteConnection conn)
  279. {
  280. da.InsertCommand = createInsertCommand("assets", ds.Tables["assets"]);
  281. da.InsertCommand.Connection = conn;
  282. da.UpdateCommand = createUpdateCommand("assets", "UUID=:UUID", ds.Tables["assets"]);
  283. da.UpdateCommand.Connection = conn;
  284. SqliteCommand delete = new SqliteCommand("delete from assets where UUID = :UUID");
  285. delete.Parameters.Add(createSqliteParameter("UUID", typeof (String)));
  286. delete.Connection = conn;
  287. da.DeleteCommand = delete;
  288. }
  289. private void InitDB(SqliteConnection conn)
  290. {
  291. string createAssets = defineTable(createAssetsTable());
  292. SqliteCommand pcmd = new SqliteCommand(createAssets, conn);
  293. conn.Open();
  294. pcmd.ExecuteNonQuery();
  295. conn.Close();
  296. }
  297. private bool TestTables(SqliteConnection conn)
  298. {
  299. SqliteCommand cmd = new SqliteCommand(assetSelect, conn);
  300. SqliteDataAdapter pDa = new SqliteDataAdapter(cmd);
  301. DataSet tmpDS = new DataSet();
  302. try
  303. {
  304. pDa.Fill(tmpDS, "assets");
  305. }
  306. catch (SqliteSyntaxException)
  307. {
  308. MainLog.Instance.Verbose("SQLITE", "SQLite Database doesn't exist... creating");
  309. InitDB(conn);
  310. }
  311. return true;
  312. }
  313. #region IPlugin interface
  314. public string Version
  315. {
  316. get
  317. {
  318. Module module = GetType().Module;
  319. string dllName = module.Assembly.ManifestModule.Name;
  320. Version dllVersion = module.Assembly.GetName().Version;
  321. return
  322. string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
  323. dllVersion.Revision);
  324. }
  325. }
  326. public void Initialise()
  327. {
  328. Initialise("AssetStorage.db", "");
  329. }
  330. public string Name
  331. {
  332. get { return "SQLite Asset storage engine"; }
  333. }
  334. #endregion
  335. }
  336. }