aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs')
-rw-r--r--OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs311
1 files changed, 311 insertions, 0 deletions
diff --git a/OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs b/OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs
new file mode 100644
index 0000000..34f1ef0
--- /dev/null
+++ b/OpenSim/Grid/NewAssetServer/Extensions/OpenSimMySQLStorage.cs
@@ -0,0 +1,311 @@
1/*
2 * Copyright (c) 2008 Intel Corporation
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * -- Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * -- Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * -- Neither the name of the Intel Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30using System;
31using System.Collections.Generic;
32using System.Net;
33using System.Data;
34using MySql.Data.MySqlClient;
35using ExtensionLoader;
36using ExtensionLoader.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40namespace AssetServer.Extensions
41{
42 public class OpenSimMySQLStorage : IExtension<AssetServer>, IStorageProvider
43 {
44 const string EXTENSION_NAME = "OpenSimMySQLStorage"; // Used in metrics reporting
45
46 AssetServer server;
47
48 public OpenSimMySQLStorage()
49 {
50 }
51
52 #region Required Interfaces
53
54 public void Start(AssetServer server)
55 {
56 this.server = server;
57
58 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
59 {
60 try
61 {
62 dbConnection.Open();
63 Logger.Log.Info("Connected to MySQL storage backend: " + dbConnection.ServerVersion);
64 }
65 catch (MySqlException ex)
66 {
67 Logger.Log.Error("Connection to MySQL storage backend failed: " + ex.Message);
68 }
69 }
70 }
71
72 public void Stop()
73 {
74 }
75
76 public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata)
77 {
78 metadata = null;
79 BackendResponse ret;
80
81 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
82 {
83 IDataReader reader;
84
85 try
86 {
87 dbConnection.Open();
88
89 IDbCommand command = dbConnection.CreateCommand();
90 command.CommandText = String.Format("SELECT name,description,assetType,temporary FROM assets WHERE id='{0}'", assetID.ToString());
91 reader = command.ExecuteReader();
92
93 if (reader.Read())
94 {
95 metadata = new Metadata();
96 metadata.CreationDate = OpenMetaverse.Utils.Epoch;
97 metadata.SHA1 = null;
98 metadata.ID = assetID;
99 metadata.Name = reader.GetString(0);
100 metadata.Description = reader.GetString(1);
101 metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
102 metadata.Temporary = reader.GetBoolean(3);
103
104 ret = BackendResponse.Success;
105 }
106 else
107 {
108 ret = BackendResponse.NotFound;
109 }
110 }
111 catch (MySqlException ex)
112 {
113 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
114 ret = BackendResponse.Failure;
115 }
116 }
117
118 server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now);
119 return ret;
120 }
121
122 public BackendResponse TryFetchData(UUID assetID, out byte[] assetData)
123 {
124 assetData = null;
125 BackendResponse ret;
126
127 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
128 {
129 IDataReader reader;
130
131 try
132 {
133 dbConnection.Open();
134
135 IDbCommand command = dbConnection.CreateCommand();
136 command.CommandText = String.Format("SELECT data FROM assets WHERE id='{0}'", assetID.ToString());
137 reader = command.ExecuteReader();
138
139 if (reader.Read())
140 {
141 assetData = (byte[])reader.GetValue(0);
142 ret = BackendResponse.Success;
143 }
144 else
145 {
146 ret = BackendResponse.NotFound;
147 }
148 }
149 catch (MySqlException ex)
150 {
151 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
152 ret = BackendResponse.Failure;
153 }
154 }
155
156 server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now);
157 return ret;
158 }
159
160 public BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData)
161 {
162 metadata = null;
163 assetData = null;
164 BackendResponse ret;
165
166 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
167 {
168 IDataReader reader;
169
170 try
171 {
172 dbConnection.Open();
173
174 IDbCommand command = dbConnection.CreateCommand();
175 command.CommandText = String.Format("SELECT name,description,assetType,temporary,data FROM assets WHERE id='{0}'", assetID.ToString());
176 reader = command.ExecuteReader();
177
178 if (reader.Read())
179 {
180 metadata = new Metadata();
181 metadata.CreationDate = OpenMetaverse.Utils.Epoch;
182 metadata.SHA1 = null;
183 metadata.ID = assetID;
184 metadata.Name = reader.GetString(0);
185 metadata.Description = reader.GetString(1);
186 metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
187 metadata.Temporary = reader.GetBoolean(3);
188
189 assetData = (byte[])reader.GetValue(4);
190
191 ret = BackendResponse.Success;
192 }
193 else
194 {
195 ret = BackendResponse.NotFound;
196 }
197 }
198 catch (MySqlException ex)
199 {
200 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
201 ret = BackendResponse.Failure;
202 }
203 }
204
205 server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now);
206 server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now);
207 return ret;
208 }
209
210 public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID)
211 {
212 assetID = metadata.ID = UUID.Random();
213 return TryCreateAsset(metadata, assetData);
214 }
215
216 public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData)
217 {
218 BackendResponse ret;
219
220 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
221 {
222 try
223 {
224 dbConnection.Open();
225
226 MySqlCommand command = new MySqlCommand(
227 "REPLACE INTO assets (name,description,assetType,local,temporary,data,id) VALUES " +
228 "(?name,?description,?assetType,?local,?temporary,?data,?id)", dbConnection);
229
230 command.Parameters.AddWithValue("?name", metadata.Name);
231 command.Parameters.AddWithValue("?description", metadata.Description);
232 command.Parameters.AddWithValue("?assetType", Utils.ContentTypeToSLAssetType(metadata.ContentType));
233 command.Parameters.AddWithValue("?local", 0);
234 command.Parameters.AddWithValue("?temporary", metadata.Temporary);
235 command.Parameters.AddWithValue("?data", assetData);
236 command.Parameters.AddWithValue("?id", metadata.ID.ToString());
237
238 int rowsAffected = command.ExecuteNonQuery();
239 if (rowsAffected == 1)
240 {
241 ret = BackendResponse.Success;
242 }
243 else if (rowsAffected == 2)
244 {
245 Logger.Log.Info("Replaced asset " + metadata.ID.ToString());
246 ret = BackendResponse.Success;
247 }
248 else
249 {
250 Logger.Log.ErrorFormat("MySQL REPLACE query affected {0} rows", rowsAffected);
251 ret = BackendResponse.Failure;
252 }
253 }
254 catch (MySqlException ex)
255 {
256 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
257 ret = BackendResponse.Failure;
258 }
259 }
260
261 server.MetricsProvider.LogAssetCreate(EXTENSION_NAME, ret, metadata.ID, assetData.Length, DateTime.Now);
262 return ret;
263 }
264
265 public int ForEach(Action<Metadata> action, int start, int count)
266 {
267 int rowCount = 0;
268
269 using (MySqlConnection dbConnection = new MySqlConnection(DBConnString.GetConnectionString(server.ConfigFile)))
270 {
271 MySqlDataReader reader;
272
273 try
274 {
275 dbConnection.Open();
276
277 MySqlCommand command = dbConnection.CreateCommand();
278 command.CommandText = String.Format("SELECT name,description,assetType,temporary,data,id FROM assets LIMIT {0}, {1}",
279 start, count);
280 reader = command.ExecuteReader();
281 }
282 catch (MySqlException ex)
283 {
284 Logger.Log.Error("Connection to MySQL backend failed: " + ex.Message);
285 return 0;
286 }
287
288 while (reader.Read())
289 {
290 Metadata metadata = new Metadata();
291 metadata.CreationDate = OpenMetaverse.Utils.Epoch;
292 metadata.Description = reader.GetString(1);
293 metadata.ID = UUID.Parse(reader.GetString(5));
294 metadata.Name = reader.GetString(0);
295 metadata.SHA1 = OpenMetaverse.Utils.SHA1((byte[])reader.GetValue(4));
296 metadata.Temporary = reader.GetBoolean(3);
297 metadata.ContentType = Utils.SLAssetTypeToContentType(reader.GetInt32(2));
298
299 action(metadata);
300 ++rowCount;
301 }
302
303 reader.Close();
304 }
305
306 return rowCount;
307 }
308
309 #endregion Required Interfaces
310 }
311}