diff options
Diffstat (limited to 'OpenSim/Grid/AssetInventoryServer')
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs | 17 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimFrontend.cs | 215 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLStorage.cs | 311 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Interfaces.cs | 10 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs | 2 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs | 2 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml | 4 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml | 13 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleAssetStoragePlugin.cs (renamed from OpenSim/Grid/AssetInventoryServer/Extensions/SimpleStorage.cs) | 70 | ||||
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleUtils.cs | 73 |
10 files changed, 148 insertions, 569 deletions
diff --git a/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs b/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs index d37c63d..e51f559 100644 --- a/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs +++ b/OpenSim/Grid/AssetInventoryServer/AssetInventoryServer.cs | |||
@@ -106,8 +106,8 @@ namespace OpenSim.Grid.AssetInventoryServer | |||
106 | return false; | 106 | return false; |
107 | } | 107 | } |
108 | 108 | ||
109 | StorageProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/StorageProvider") as IAssetStorageProvider; | 109 | StorageProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/StorageProvider", "OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll") as IAssetStorageProvider; |
110 | MetricsProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/MetricsProvider") as IMetricsProvider; | 110 | MetricsProvider = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/MetricsProvider", "") as IMetricsProvider; |
111 | 111 | ||
112 | try | 112 | try |
113 | { | 113 | { |
@@ -120,7 +120,7 @@ namespace OpenSim.Grid.AssetInventoryServer | |||
120 | return false; | 120 | return false; |
121 | } | 121 | } |
122 | 122 | ||
123 | frontend = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/Frontend"); | 123 | frontend = LoadAssetInventoryServerPlugin("/OpenSim/AssetInventoryServer/Frontend", ""); |
124 | 124 | ||
125 | return true; | 125 | return true; |
126 | } | 126 | } |
@@ -179,13 +179,16 @@ namespace OpenSim.Grid.AssetInventoryServer | |||
179 | 179 | ||
180 | #endregion | 180 | #endregion |
181 | 181 | ||
182 | private IAssetInventoryServerPlugin LoadAssetInventoryServerPlugin(string addinPath) | 182 | private IAssetInventoryServerPlugin LoadAssetInventoryServerPlugin(string addinPath, string provider) |
183 | { | 183 | { |
184 | PluginLoader<IAssetInventoryServerPlugin> loader = new PluginLoader<IAssetInventoryServerPlugin>(new AssetInventoryServerPluginInitialiser(this)); | 184 | PluginLoader<IAssetInventoryServerPlugin> loader = new PluginLoader<IAssetInventoryServerPlugin>(new AssetInventoryServerPluginInitialiser(this)); |
185 | 185 | ||
186 | //loader.Add ("/OpenSim/AssetInventoryServer/StorageProvider", new PluginProviderFilter (provider)); | 186 | if (provider == String.Empty) |
187 | //loader.Add("/OpenSim/AssetInventoryServer/StorageProvider", new PluginCountConstraint(1)); | 187 | loader.Add(addinPath); |
188 | loader.Add(addinPath); | 188 | else |
189 | loader.Add(addinPath, new PluginProviderFilter(provider)); | ||
190 | //loader.Add(addinPath, new PluginCountConstraint(1)); | ||
191 | |||
189 | loader.Load(); | 192 | loader.Load(); |
190 | 193 | ||
191 | return loader.Plugin; | 194 | return loader.Plugin; |
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimFrontend.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimFrontend.cs deleted file mode 100644 index e34a235..0000000 --- a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimFrontend.cs +++ /dev/null | |||
@@ -1,215 +0,0 @@ | |||
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 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.IO; | ||
34 | using System.Xml; | ||
35 | using ExtensionLoader; | ||
36 | using OpenMetaverse; | ||
37 | using HttpServer; | ||
38 | |||
39 | namespace OpenSim.Grid.AssetInventoryServer.Extensions | ||
40 | { | ||
41 | public class OpenSimFrontend : IExtension<AssetInventoryServer> | ||
42 | { | ||
43 | AssetInventoryServer server; | ||
44 | |||
45 | public OpenSimFrontend() | ||
46 | { | ||
47 | } | ||
48 | |||
49 | public void Start(AssetInventoryServer server) | ||
50 | { | ||
51 | this.server = server; | ||
52 | |||
53 | // Asset request | ||
54 | server.HttpServer.AddHandler("get", null, @"^/assets/", AssetRequestHandler); | ||
55 | |||
56 | // Asset creation | ||
57 | server.HttpServer.AddHandler("post", null, @"^/assets/", AssetPostHandler); | ||
58 | } | ||
59 | |||
60 | public void Stop() | ||
61 | { | ||
62 | } | ||
63 | |||
64 | bool AssetRequestHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
65 | { | ||
66 | UUID assetID; | ||
67 | // Split the URL up to get the asset ID out | ||
68 | string[] rawUrl = request.Uri.PathAndQuery.Split('/'); | ||
69 | |||
70 | if (rawUrl.Length >= 3 && rawUrl[2].Length >= 36 && UUID.TryParse(rawUrl[2].Substring(0, 36), out assetID)) | ||
71 | { | ||
72 | Metadata metadata; | ||
73 | byte[] assetData; | ||
74 | BackendResponse dataResponse; | ||
75 | |||
76 | if ((dataResponse = server.StorageProvider.TryFetchDataMetadata(assetID, out metadata, out assetData)) == BackendResponse.Success) | ||
77 | { | ||
78 | MemoryStream stream = new MemoryStream(); | ||
79 | |||
80 | XmlWriterSettings settings = new XmlWriterSettings(); | ||
81 | settings.Indent = true; | ||
82 | XmlWriter writer = XmlWriter.Create(stream, settings); | ||
83 | |||
84 | writer.WriteStartDocument(); | ||
85 | writer.WriteStartElement("AssetBase"); | ||
86 | writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); | ||
87 | writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); | ||
88 | writer.WriteStartElement("FullID"); | ||
89 | writer.WriteStartElement("Guid"); | ||
90 | writer.WriteString(assetID.ToString()); | ||
91 | writer.WriteEndElement(); | ||
92 | writer.WriteEndElement(); | ||
93 | writer.WriteStartElement("ID"); | ||
94 | writer.WriteString(assetID.ToString()); | ||
95 | writer.WriteEndElement(); | ||
96 | writer.WriteStartElement("Data"); | ||
97 | writer.WriteBase64(assetData, 0, assetData.Length); | ||
98 | writer.WriteEndElement(); | ||
99 | writer.WriteStartElement("Type"); | ||
100 | writer.WriteValue(Utils.ContentTypeToSLAssetType(metadata.ContentType)); | ||
101 | writer.WriteEndElement(); | ||
102 | writer.WriteStartElement("Name"); | ||
103 | writer.WriteString(metadata.Name); | ||
104 | writer.WriteEndElement(); | ||
105 | writer.WriteStartElement("Description"); | ||
106 | writer.WriteString(metadata.Description); | ||
107 | writer.WriteEndElement(); | ||
108 | writer.WriteStartElement("Local"); | ||
109 | writer.WriteValue(false); | ||
110 | writer.WriteEndElement(); | ||
111 | writer.WriteStartElement("Temporary"); | ||
112 | writer.WriteValue(metadata.Temporary); | ||
113 | writer.WriteEndElement(); | ||
114 | writer.WriteEndElement(); | ||
115 | writer.WriteEndDocument(); | ||
116 | |||
117 | writer.Flush(); | ||
118 | byte[] buffer = stream.GetBuffer(); | ||
119 | |||
120 | response.Status = HttpStatusCode.OK; | ||
121 | response.ContentType = "application/xml"; | ||
122 | response.ContentLength = stream.Length; | ||
123 | response.Body.Write(buffer, 0, (int)stream.Length); | ||
124 | response.Body.Flush(); | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | Logger.Log.WarnFormat("Failed to fetch asset data or metadata for {0}: {1}", assetID, dataResponse); | ||
129 | response.Status = HttpStatusCode.NotFound; | ||
130 | } | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | Logger.Log.Warn("Unrecognized OpenSim asset request: " + request.Uri.PathAndQuery); | ||
135 | } | ||
136 | |||
137 | return true; | ||
138 | } | ||
139 | |||
140 | bool AssetPostHandler(IHttpClientContext client, IHttpRequest request, IHttpResponse response) | ||
141 | { | ||
142 | byte[] assetData = null; | ||
143 | Metadata metadata = new Metadata(); | ||
144 | |||
145 | Logger.Log.Debug("Handling OpenSim asset upload"); | ||
146 | |||
147 | try | ||
148 | { | ||
149 | using (XmlReader reader = XmlReader.Create(request.Body)) | ||
150 | { | ||
151 | reader.MoveToContent(); | ||
152 | reader.ReadStartElement("AssetBase"); | ||
153 | |||
154 | reader.ReadStartElement("FullID"); | ||
155 | UUID.TryParse(reader.ReadElementContentAsString("Guid", String.Empty), out metadata.ID); | ||
156 | reader.ReadEndElement(); | ||
157 | reader.ReadStartElement("ID"); | ||
158 | reader.Skip(); | ||
159 | reader.ReadEndElement(); | ||
160 | |||
161 | // HACK: Broken on Mono. https://bugzilla.novell.com/show_bug.cgi?id=464229 | ||
162 | //int readBytes = 0; | ||
163 | //byte[] buffer = new byte[1024]; | ||
164 | //MemoryStream stream = new MemoryStream(); | ||
165 | //BinaryWriter writer = new BinaryWriter(stream); | ||
166 | //while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, buffer.Length)) > 0) | ||
167 | // writer.Write(buffer, 0, readBytes); | ||
168 | //writer.Flush(); | ||
169 | //assetData = stream.GetBuffer(); | ||
170 | //Array.Resize<byte>(ref assetData, (int)stream.Length); | ||
171 | |||
172 | assetData = Convert.FromBase64String(reader.ReadElementContentAsString()); | ||
173 | |||
174 | int type; | ||
175 | Int32.TryParse(reader.ReadElementContentAsString("Type", String.Empty), out type); | ||
176 | metadata.ContentType = Utils.SLAssetTypeToContentType(type); | ||
177 | metadata.Name = reader.ReadElementContentAsString("Name", String.Empty); | ||
178 | metadata.Description = reader.ReadElementContentAsString("Description", String.Empty); | ||
179 | Boolean.TryParse(reader.ReadElementContentAsString("Local", String.Empty), out metadata.Temporary); | ||
180 | Boolean.TryParse(reader.ReadElementContentAsString("Temporary", String.Empty), out metadata.Temporary); | ||
181 | |||
182 | reader.ReadEndElement(); | ||
183 | } | ||
184 | |||
185 | if (assetData != null && assetData.Length > 0) | ||
186 | { | ||
187 | metadata.SHA1 = OpenMetaverse.Utils.SHA1(assetData); | ||
188 | metadata.CreationDate = DateTime.Now; | ||
189 | |||
190 | BackendResponse storageResponse = server.StorageProvider.TryCreateAsset(metadata, assetData); | ||
191 | |||
192 | if (storageResponse == BackendResponse.Success) | ||
193 | response.Status = HttpStatusCode.Created; | ||
194 | else if (storageResponse == BackendResponse.NotFound) | ||
195 | response.Status = HttpStatusCode.NotFound; | ||
196 | else | ||
197 | response.Status = HttpStatusCode.InternalServerError; | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | Logger.Log.Warn("AssetPostHandler called with no asset data"); | ||
202 | response.Status = HttpStatusCode.BadRequest; | ||
203 | } | ||
204 | } | ||
205 | catch (Exception ex) | ||
206 | { | ||
207 | Logger.Log.Warn("Failed to parse POST data (expecting AssetBase): " + ex.Message); | ||
208 | response.Status = HttpStatusCode.BadRequest; | ||
209 | } | ||
210 | |||
211 | Logger.Log.Debug("Finished handling OpenSim asset upload, Status: " + response.Status.ToString()); | ||
212 | return true; | ||
213 | } | ||
214 | } | ||
215 | } | ||
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLStorage.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLStorage.cs deleted file mode 100644 index 48fa25b..0000000 --- a/OpenSim/Grid/AssetInventoryServer/Extensions/OpenSimMySQLStorage.cs +++ /dev/null | |||
@@ -1,311 +0,0 @@ | |||
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 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.Data; | ||
34 | using MySql.Data.MySqlClient; | ||
35 | using ExtensionLoader; | ||
36 | using ExtensionLoader.Config; | ||
37 | using OpenMetaverse; | ||
38 | using OpenMetaverse.StructuredData; | ||
39 | |||
40 | namespace OpenSim.Grid.AssetInventoryServer.Extensions | ||
41 | { | ||
42 | public class OpenSimMySQLStorage : IExtension<AssetInventoryServer>, IStorageProvider | ||
43 | { | ||
44 | const string EXTENSION_NAME = "OpenSimMySQLStorage"; // Used in metrics reporting | ||
45 | |||
46 | AssetInventoryServer server; | ||
47 | |||
48 | public OpenSimMySQLStorage() | ||
49 | { | ||
50 | } | ||
51 | |||
52 | #region Required Interfaces | ||
53 | |||
54 | public void Start(AssetInventoryServer 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 | } | ||
diff --git a/OpenSim/Grid/AssetInventoryServer/Interfaces.cs b/OpenSim/Grid/AssetInventoryServer/Interfaces.cs index 67ffa2f..870cf89 100644 --- a/OpenSim/Grid/AssetInventoryServer/Interfaces.cs +++ b/OpenSim/Grid/AssetInventoryServer/Interfaces.cs | |||
@@ -73,16 +73,6 @@ namespace OpenSim.Grid.AssetInventoryServer | |||
73 | void Initialise(AssetInventoryServer server); | 73 | void Initialise(AssetInventoryServer server); |
74 | } | 74 | } |
75 | 75 | ||
76 | public interface IStorageProvider | ||
77 | { | ||
78 | BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata); | ||
79 | BackendResponse TryFetchData(UUID assetID, out byte[] assetData); | ||
80 | BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData); | ||
81 | BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData); | ||
82 | BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID); | ||
83 | int ForEach(Action<Metadata> action, int start, int count); | ||
84 | } | ||
85 | |||
86 | public interface IAssetStorageProvider : IAssetInventoryServerPlugin | 76 | public interface IAssetStorageProvider : IAssetInventoryServerPlugin |
87 | { | 77 | { |
88 | BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata); | 78 | BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata); |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs index 0326771..f0ad3cf 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetFrontendPlugin.cs | |||
@@ -39,7 +39,7 @@ using OpenMetaverse; | |||
39 | using HttpServer; | 39 | using HttpServer; |
40 | using OpenSim.Framework; | 40 | using OpenSim.Framework; |
41 | 41 | ||
42 | namespace OpenSim.Grid.AssetInventoryServer.Plugins | 42 | namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim |
43 | { | 43 | { |
44 | public class OpenSimAssetFrontendPlugin : IAssetInventoryServerPlugin | 44 | public class OpenSimAssetFrontendPlugin : IAssetInventoryServerPlugin |
45 | { | 45 | { |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs index 37dd241..6c02cde 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/OpenSimAssetStoragePlugin.cs | |||
@@ -40,7 +40,7 @@ using OpenSim.Framework; | |||
40 | using OpenSim.Grid.AssetInventoryServer.Extensions; | 40 | using OpenSim.Grid.AssetInventoryServer.Extensions; |
41 | using OpenSim.Data; | 41 | using OpenSim.Data; |
42 | 42 | ||
43 | namespace OpenSim.Grid.AssetInventoryServer.Plugins | 43 | namespace OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim |
44 | { | 44 | { |
45 | public class OpenSimAssetStoragePlugin : IAssetStorageProvider | 45 | public class OpenSimAssetStoragePlugin : IAssetStorageProvider |
46 | { | 46 | { |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml index 0fe2f48..f458909 100644 --- a/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/OpenSim/Resources/AssetInventoryServerOpenSimPlugins.addin.xml | |||
@@ -13,9 +13,9 @@ | |||
13 | </ExtensionPoint> | 13 | </ExtensionPoint> |
14 | 14 | ||
15 | <Extension path="/OpenSim/AssetInventoryServer/StorageProvider"> | 15 | <Extension path="/OpenSim/AssetInventoryServer/StorageProvider"> |
16 | <Plugin id="OpenSimAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSimAssetStoragePlugin" /> | 16 | <Plugin id="OpenSimAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetStoragePlugin" /> |
17 | </Extension> | 17 | </Extension> |
18 | <Extension path="/OpenSim/AssetInventoryServer/Frontend"> | 18 | <Extension path="/OpenSim/AssetInventoryServer/Frontend"> |
19 | <Plugin id="OpenSimAssetFrontend" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSimAssetFrontendPlugin" /> | 19 | <Plugin id="OpenSimAssetFrontend" provider="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.OpenSim.OpenSimAssetFrontendPlugin" /> |
20 | </Extension> | 20 | </Extension> |
21 | </Addin> | 21 | </Addin> |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml new file mode 100644 index 0000000..53534c4 --- /dev/null +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/Resources/AssetInventoryServerSimplePlugins.addin.xml | |||
@@ -0,0 +1,13 @@ | |||
1 | <Addin id="OpenSim.Grid.AssetInventoryServer.Plugins.Simple" version="0.1"> | ||
2 | <Runtime> | ||
3 | <Import assembly="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" /> | ||
4 | </Runtime> | ||
5 | |||
6 | <Dependencies> | ||
7 | <Addin id="OpenSim.Grid.AssetInventoryServer" version="0.1" /> | ||
8 | </Dependencies> | ||
9 | |||
10 | <Extension path="/OpenSim/AssetInventoryServer/StorageProvider"> | ||
11 | <Plugin id="SimpleAssetStorage" provider="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.dll" type="OpenSim.Grid.AssetInventoryServer.Plugins.Simple.SimpleAssetStoragePlugin" /> | ||
12 | </Extension> | ||
13 | </Addin> | ||
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleStorage.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleAssetStoragePlugin.cs index 9456ef5..fd198d9 100644 --- a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleStorage.cs +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleAssetStoragePlugin.cs | |||
@@ -34,12 +34,13 @@ using System.IO; | |||
34 | using ExtensionLoader; | 34 | using ExtensionLoader; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenMetaverse.StructuredData; | 36 | using OpenMetaverse.StructuredData; |
37 | using OpenSim.Framework; | ||
37 | 38 | ||
38 | namespace OpenSim.Grid.AssetInventoryServer.Extensions | 39 | namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple |
39 | { | 40 | { |
40 | public class SimpleStorage : IExtension<AssetInventoryServer>, IStorageProvider | 41 | public class SimpleAssetStoragePlugin : IAssetStorageProvider |
41 | { | 42 | { |
42 | const string EXTENSION_NAME = ""; // Used in metrics reporting | 43 | const string EXTENSION_NAME = "SimpleAssetStorage"; // Used in metrics reporting |
43 | const string DEFAULT_DATA_DIR = "SimpleAssets"; | 44 | const string DEFAULT_DATA_DIR = "SimpleAssets"; |
44 | const string TEMP_DATA_DIR = "SimpleAssetsTemp"; | 45 | const string TEMP_DATA_DIR = "SimpleAssetsTemp"; |
45 | 46 | ||
@@ -47,30 +48,12 @@ namespace OpenSim.Grid.AssetInventoryServer.Extensions | |||
47 | Dictionary<UUID, Metadata> metadataStorage; | 48 | Dictionary<UUID, Metadata> metadataStorage; |
48 | Dictionary<UUID, string> filenames; | 49 | Dictionary<UUID, string> filenames; |
49 | 50 | ||
50 | public SimpleStorage() | 51 | public SimpleAssetStoragePlugin() |
51 | { | 52 | { |
52 | } | 53 | } |
53 | 54 | ||
54 | #region Required Interfaces | 55 | #region Required Interfaces |
55 | 56 | ||
56 | public void Start(AssetInventoryServer server) | ||
57 | { | ||
58 | this.server = server; | ||
59 | metadataStorage = new Dictionary<UUID, Metadata>(); | ||
60 | filenames = new Dictionary<UUID, string>(); | ||
61 | |||
62 | LoadFiles(DEFAULT_DATA_DIR, false); | ||
63 | LoadFiles(TEMP_DATA_DIR, true); | ||
64 | |||
65 | Logger.Log.InfoFormat("Initialized the store index with metadata for {0} assets", | ||
66 | metadataStorage.Count); | ||
67 | } | ||
68 | |||
69 | public void Stop() | ||
70 | { | ||
71 | WipeTemporary(); | ||
72 | } | ||
73 | |||
74 | public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata) | 57 | public BackendResponse TryFetchMetadata(UUID assetID, out Metadata metadata) |
75 | { | 58 | { |
76 | metadata = null; | 59 | metadata = null; |
@@ -203,6 +186,49 @@ namespace OpenSim.Grid.AssetInventoryServer.Extensions | |||
203 | 186 | ||
204 | #endregion Required Interfaces | 187 | #endregion Required Interfaces |
205 | 188 | ||
189 | #region IPlugin implementation | ||
190 | |||
191 | public void Initialise(AssetInventoryServer server) | ||
192 | { | ||
193 | this.server = server; | ||
194 | |||
195 | metadataStorage = new Dictionary<UUID, Metadata>(); | ||
196 | filenames = new Dictionary<UUID, string>(); | ||
197 | |||
198 | LoadFiles(DEFAULT_DATA_DIR, false); | ||
199 | LoadFiles(TEMP_DATA_DIR, true); | ||
200 | |||
201 | Logger.Log.InfoFormat("Initialized the store index with metadata for {0} assets", | ||
202 | metadataStorage.Count); | ||
203 | } | ||
204 | |||
205 | /// <summary> | ||
206 | /// <para>Initialises asset interface</para> | ||
207 | /// </summary> | ||
208 | public void Initialise() | ||
209 | { | ||
210 | Logger.Log.InfoFormat("[ASSET]: {0} cannot be default-initialized!", Name); | ||
211 | throw new PluginNotInitialisedException(Name); | ||
212 | } | ||
213 | |||
214 | public void Dispose() | ||
215 | { | ||
216 | WipeTemporary(); | ||
217 | } | ||
218 | |||
219 | public string Version | ||
220 | { | ||
221 | // TODO: this should be something meaningful and not hardcoded? | ||
222 | get { return "0.1"; } | ||
223 | } | ||
224 | |||
225 | public string Name | ||
226 | { | ||
227 | get { return "AssetInventoryServer Simple asset storage provider"; } | ||
228 | } | ||
229 | |||
230 | #endregion IPlugin implementation | ||
231 | |||
206 | public void WipeTemporary() | 232 | public void WipeTemporary() |
207 | { | 233 | { |
208 | if (Directory.Exists(TEMP_DATA_DIR)) | 234 | if (Directory.Exists(TEMP_DATA_DIR)) |
diff --git a/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleUtils.cs b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleUtils.cs new file mode 100644 index 0000000..6a32718 --- /dev/null +++ b/OpenSim/Grid/AssetInventoryServer/Plugins/Simple/SimpleUtils.cs | |||
@@ -0,0 +1,73 @@ | |||
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 | |||
30 | using System; | ||
31 | using System.IO; | ||
32 | using OpenMetaverse; | ||
33 | |||
34 | namespace OpenSim.Grid.AssetInventoryServer.Plugins.Simple | ||
35 | { | ||
36 | public static class SimpleUtils | ||
37 | { | ||
38 | public static string ParseNameFromFilename(string filename) | ||
39 | { | ||
40 | filename = Path.GetFileName(filename); | ||
41 | |||
42 | int dot = filename.LastIndexOf('.'); | ||
43 | int firstDash = filename.IndexOf('-'); | ||
44 | |||
45 | if (dot - 37 > 0 && firstDash > 0) | ||
46 | return filename.Substring(0, firstDash); | ||
47 | else | ||
48 | return String.Empty; | ||
49 | } | ||
50 | |||
51 | public static UUID ParseUUIDFromFilename(string filename) | ||
52 | { | ||
53 | int dot = filename.LastIndexOf('.'); | ||
54 | |||
55 | if (dot > 35) | ||
56 | { | ||
57 | // Grab the last 36 characters of the filename | ||
58 | string uuidString = filename.Substring(dot - 36, 36); | ||
59 | UUID uuid; | ||
60 | UUID.TryParse(uuidString, out uuid); | ||
61 | return uuid; | ||
62 | } | ||
63 | else | ||
64 | { | ||
65 | UUID uuid; | ||
66 | if (UUID.TryParse(Path.GetFileName(filename), out uuid)) | ||
67 | return uuid; | ||
68 | else | ||
69 | return UUID.Zero; | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | } | ||