diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Grid/NewAssetServer/Extensions/SimpleStorage.cs | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/OpenSim/Grid/NewAssetServer/Extensions/SimpleStorage.cs b/OpenSim/Grid/NewAssetServer/Extensions/SimpleStorage.cs new file mode 100644 index 0000000..1c0fe33 --- /dev/null +++ b/OpenSim/Grid/NewAssetServer/Extensions/SimpleStorage.cs | |||
@@ -0,0 +1,260 @@ | |||
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 ExtensionLoader; | ||
35 | using OpenMetaverse; | ||
36 | using OpenMetaverse.StructuredData; | ||
37 | |||
38 | namespace AssetServer.Extensions | ||
39 | { | ||
40 | public class SimpleStorage : IExtension<AssetServer>, IStorageProvider | ||
41 | { | ||
42 | const string EXTENSION_NAME = ""; // Used in metrics reporting | ||
43 | const string DEFAULT_DATA_DIR = "SimpleAssets"; | ||
44 | const string TEMP_DATA_DIR = "SimpleAssetsTemp"; | ||
45 | |||
46 | AssetServer server; | ||
47 | Dictionary<UUID, Metadata> metadataStorage; | ||
48 | Dictionary<UUID, string> filenames; | ||
49 | |||
50 | public SimpleStorage() | ||
51 | { | ||
52 | } | ||
53 | |||
54 | #region Required Interfaces | ||
55 | |||
56 | public void Start(AssetServer 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) | ||
75 | { | ||
76 | metadata = null; | ||
77 | BackendResponse ret; | ||
78 | |||
79 | if (metadataStorage.TryGetValue(assetID, out metadata)) | ||
80 | ret = BackendResponse.Success; | ||
81 | else | ||
82 | ret = BackendResponse.NotFound; | ||
83 | |||
84 | server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | public BackendResponse TryFetchData(UUID assetID, out byte[] assetData) | ||
89 | { | ||
90 | assetData = null; | ||
91 | string filename; | ||
92 | BackendResponse ret; | ||
93 | |||
94 | if (filenames.TryGetValue(assetID, out filename)) | ||
95 | { | ||
96 | try | ||
97 | { | ||
98 | assetData = File.ReadAllBytes(filename); | ||
99 | ret = BackendResponse.Success; | ||
100 | } | ||
101 | catch (Exception ex) | ||
102 | { | ||
103 | Logger.Log.ErrorFormat("Failed reading data for asset {0} from {1}: {2}", assetID, filename, ex.Message); | ||
104 | ret = BackendResponse.Failure; | ||
105 | } | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | ret = BackendResponse.NotFound; | ||
110 | } | ||
111 | |||
112 | server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | public BackendResponse TryFetchDataMetadata(UUID assetID, out Metadata metadata, out byte[] assetData) | ||
117 | { | ||
118 | metadata = null; | ||
119 | assetData = null; | ||
120 | string filename; | ||
121 | BackendResponse ret; | ||
122 | |||
123 | if (metadataStorage.TryGetValue(assetID, out metadata) && | ||
124 | filenames.TryGetValue(assetID, out filename)) | ||
125 | { | ||
126 | try | ||
127 | { | ||
128 | assetData = File.ReadAllBytes(filename); | ||
129 | ret = BackendResponse.Success; | ||
130 | } | ||
131 | catch (Exception ex) | ||
132 | { | ||
133 | Logger.Log.ErrorFormat("Failed reading data for asset {0} from {1}: {2}", assetID, filename, ex.Message); | ||
134 | ret = BackendResponse.Failure; | ||
135 | } | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | ret = BackendResponse.NotFound; | ||
140 | } | ||
141 | |||
142 | server.MetricsProvider.LogAssetMetadataFetch(EXTENSION_NAME, ret, assetID, DateTime.Now); | ||
143 | server.MetricsProvider.LogAssetDataFetch(EXTENSION_NAME, ret, assetID, (assetData != null ? assetData.Length : 0), DateTime.Now); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData, out UUID assetID) | ||
148 | { | ||
149 | assetID = metadata.ID = UUID.Random(); | ||
150 | return TryCreateAsset(metadata, assetData); | ||
151 | } | ||
152 | |||
153 | public BackendResponse TryCreateAsset(Metadata metadata, byte[] assetData) | ||
154 | { | ||
155 | BackendResponse ret; | ||
156 | |||
157 | string path; | ||
158 | string filename = String.Format("{0}.{1}", metadata.ID, Utils.ContentTypeToExtension(metadata.ContentType)); | ||
159 | |||
160 | if (metadata.Temporary) | ||
161 | path = Path.Combine(TEMP_DATA_DIR, filename); | ||
162 | else | ||
163 | path = Path.Combine(DEFAULT_DATA_DIR, filename); | ||
164 | |||
165 | try | ||
166 | { | ||
167 | File.WriteAllBytes(path, assetData); | ||
168 | lock (filenames) filenames[metadata.ID] = path; | ||
169 | |||
170 | // Set the creation date to right now | ||
171 | metadata.CreationDate = DateTime.Now; | ||
172 | |||
173 | lock (metadataStorage) | ||
174 | metadataStorage[metadata.ID] = metadata; | ||
175 | |||
176 | ret = BackendResponse.Success; | ||
177 | } | ||
178 | catch (Exception ex) | ||
179 | { | ||
180 | Logger.Log.ErrorFormat("Failed writing data for asset {0} to {1}: {2}", metadata.ID, filename, ex.Message); | ||
181 | ret = BackendResponse.Failure; | ||
182 | } | ||
183 | |||
184 | server.MetricsProvider.LogAssetCreate(EXTENSION_NAME, ret, metadata.ID, assetData.Length, DateTime.Now); | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | public int ForEach(Action<Metadata> action, int start, int count) | ||
189 | { | ||
190 | int rowCount = 0; | ||
191 | |||
192 | lock (metadataStorage) | ||
193 | { | ||
194 | foreach (Metadata metadata in metadataStorage.Values) | ||
195 | { | ||
196 | action(metadata); | ||
197 | ++rowCount; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | return rowCount; | ||
202 | } | ||
203 | |||
204 | #endregion Required Interfaces | ||
205 | |||
206 | public void WipeTemporary() | ||
207 | { | ||
208 | if (Directory.Exists(TEMP_DATA_DIR)) | ||
209 | { | ||
210 | try { Directory.Delete(TEMP_DATA_DIR); } | ||
211 | catch (Exception ex) { Logger.Log.Error(ex.Message); } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | void LoadFiles(string folder, bool temporary) | ||
216 | { | ||
217 | // Try to create the directory if it doesn't already exist | ||
218 | if (!Directory.Exists(folder)) | ||
219 | { | ||
220 | try { Directory.CreateDirectory(folder); } | ||
221 | catch (Exception ex) | ||
222 | { | ||
223 | Logger.Log.Warn(ex.Message); | ||
224 | return; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | lock (metadataStorage) | ||
229 | { | ||
230 | try | ||
231 | { | ||
232 | string[] assets = Directory.GetFiles(folder); | ||
233 | |||
234 | for (int i = 0; i < assets.Length; i++) | ||
235 | { | ||
236 | string filename = assets[i]; | ||
237 | byte[] data = File.ReadAllBytes(filename); | ||
238 | |||
239 | Metadata metadata = new Metadata(); | ||
240 | metadata.CreationDate = File.GetCreationTime(filename); | ||
241 | metadata.Description = String.Empty; | ||
242 | metadata.ID = SimpleUtils.ParseUUIDFromFilename(filename); | ||
243 | metadata.Name = SimpleUtils.ParseNameFromFilename(filename); | ||
244 | metadata.SHA1 = OpenMetaverse.Utils.SHA1(data); | ||
245 | metadata.Temporary = false; | ||
246 | metadata.ContentType = Utils.ExtensionToContentType(Path.GetExtension(filename).TrimStart('.')); | ||
247 | |||
248 | // Store the loaded data | ||
249 | metadataStorage[metadata.ID] = metadata; | ||
250 | filenames[metadata.ID] = filename; | ||
251 | } | ||
252 | } | ||
253 | catch (Exception ex) | ||
254 | { | ||
255 | Logger.Log.Warn(ex.Message); | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | } | ||