4 using System.Collections.Generic;
7 using SiliconStudio.Core.IO;
8 using SiliconStudio.Core.Serialization.Assets;
10 namespace SiliconStudio.Core.Storage
17 private const int WriteBufferSize = 1024;
18 private bool isReadOnly;
22 private readonly
string vfsRootUrl;
23 private readonly
string vfsTempUrl;
29 get {
return assetIndexMap; }
32 public FileOdbBackend(
string vfsRootUrl,
bool isReadOnly,
string indexName =
"index")
34 var resolveProviderResult = VirtualFileSystem.ResolveProvider(vfsRootUrl,
true);
35 virtualFileProvider = resolveProviderResult.Provider;
36 this.vfsRootUrl = resolveProviderResult.Path;
37 vfsTempUrl = this.vfsRootUrl +
"/tmp/";
40 if (!virtualFileProvider.DirectoryExists(
this.vfsRootUrl))
41 virtualFileProvider.CreateDirectory(
this.vfsRootUrl);
43 this.isReadOnly = isReadOnly;
45 assetIndexMap = Serialization.Assets.AssetIndexMap.Load(vfsRootUrl + VirtualFileSystem.DirectorySeparatorChar + indexName, isReadOnly);
46 if (!isReadOnly && !virtualFileProvider.DirectoryExists(vfsTempUrl))
50 virtualFileProvider.CreateDirectory(vfsTempUrl);
54 this.isReadOnly =
true;
59 public bool IsReadOnly
61 get {
return isReadOnly; }
67 var url = BuildUrl(vfsRootUrl, objectId);
71 if (!virtualFileProvider.FileExists(url))
77 virtualFileProvider.CreateDirectory(ExtractPath(url));
83 return virtualFileProvider.OpenStream(url, mode, access, share);
85 catch (FileNotFoundException)
89 #if !SILICONSTUDIO_PLATFORM_WINDOWS_RUNTIME
90 catch (DirectoryNotFoundException)
100 var url = BuildUrl(vfsRootUrl, objectId);
101 using (var file = virtualFileProvider.OpenStream(url, VirtualFileMode.Open, VirtualFileAccess.Read))
103 return checked((
int)file.Length);
110 var url = BuildUrl(vfsRootUrl, objectId);
111 return virtualFileProvider.FileExists(url);
122 dataStream.CopyTo(digestStream);
123 objectId = digestStream.CurrentHash;
126 dataStream.Seek(0, SeekOrigin.Begin);
129 var url = BuildUrl(vfsRootUrl, objectId);
131 if (!forceWrite && virtualFileProvider.FileExists(url))
134 virtualFileProvider.CreateDirectory(ExtractPath(url));
135 using (var file = virtualFileProvider.OpenStream(url, VirtualFileMode.Create, VirtualFileAccess.Write))
138 var buffer =
new byte[WriteBufferSize];
139 for (
int offset = 0; offset < length; offset += WriteBufferSize)
141 int blockSize = length - offset;
142 if (blockSize > WriteBufferSize)
143 blockSize = WriteBufferSize;
145 dataStream.Read(buffer, 0, blockSize);
146 file.Write(buffer, 0, blockSize);
157 throw new InvalidOperationException(
"Read-only backend.");
159 string tmpFileName = vfsTempUrl + Guid.NewGuid() +
".tmp";
160 Stream stream = virtualFileProvider.OpenStream(tmpFileName, VirtualFileMode.Create, VirtualFileAccess.Write);
161 return new DigestStream(stream, tmpFileName) { Disposed = x => SaveStream(x) };
167 ObjectId objId = stream.CurrentHash;
168 string fileUrl = BuildUrl(vfsRootUrl, objId);
170 string temporaryFilePath = stream.TemporaryName;
173 if (!virtualFileProvider.FileExists(fileUrl))
178 virtualFileProvider.CreateDirectory(fileUrl.Substring(0, fileUrl.Length - (ObjectId.HashStringLength - 2)));
179 virtualFileProvider.FileMove(temporaryFilePath, BuildUrl(vfsRootUrl, objId));
181 catch (IOException e)
186 if (e.GetType() != typeof(IOException))
190 virtualFileProvider.FileDelete(temporaryFilePath);
196 virtualFileProvider.FileDelete(temporaryFilePath);
205 var url = BuildUrl(vfsRootUrl, objectId);
206 virtualFileProvider.FileDelete(url);
212 foreach (var file
in virtualFileProvider.ListFiles(vfsRootUrl,
"*",
VirtualSearchOption.AllDirectories))
220 var objectIdString =
new char[ObjectId.HashStringLength];
221 var filePosition = file.Length - ObjectId.HashStringLength - 1;
222 for (
int i = 0; i < ObjectId.HashStringLength; ++i)
227 objectIdString[i] = file[filePosition++];
232 yield
return objectId;
239 return virtualFileProvider.GetAbsolutePath(BuildUrl(vfsRootUrl, objectId));
242 private static string ExtractPath(
string url)
244 return url.Substring(0, url.LastIndexOf(
'/'));
249 var
id = objectId.ToString();
251 result.Append(vfsRootUrl);
253 result.Append(
id[0]);
254 result.Append(
id[1]);
256 result.Append(id, 2, ObjectId.HashStringLength - 2);
258 return result.ToString();
virtual Stream OpenStream(ObjectId objectId, VirtualFileMode mode=VirtualFileMode.Open, VirtualFileAccess access=VirtualFileAccess.Read, VirtualFileShare share=VirtualFileShare.Read)
Opens a NativeStream of the object with the specified ObjectId. The ObjectId.The mode.The access.The process share mode.A NativeStream opened from the specified ObjectId.
A virtual file provider, that can returns a Stream for a given path.
Virtual abstraction over a file system. It handles access to files, http, packages, path rewrite, etc...
static string BuildUrl(string vfsRootUrl, ObjectId objectId)
virtual ObjectId Write(ObjectId objectId, Stream dataStream, int length, bool forceWrite=false)
Writes an object to the backing store. The backend may need to compute the object ID and return it to...
VirtualFileShare
File share capabilities, equivalent of System.IO.FileShare.
const int HashStringLength
static readonly char DirectorySeparatorChar
Base class for custom object database backends (ODB).
FileOdbBackend(string vfsRootUrl, bool isReadOnly, string indexName="index")
void Delete(ObjectId objectId)
Deletes the specified ObjectId. The object id.
Object Database Backend (ODB) implementation using VirtualFileSystem
VirtualFileAccess
File access equivalent of System.IO.FileAccess.
VirtualFileMode
File mode equivalent of System.IO.FileMode.
static readonly ObjectId Empty
A hash to uniquely identify data.
virtual bool Exists(ObjectId objectId)
Determines weither the object with the specified ObjectId exists. The ObjectId to check existence for...
string GetFilePath(ObjectId objectId)
Returns the file path corresponding to the given id (in the VFS domain), if appliable.
IEnumerable< ObjectId > EnumerateObjects()
Enumerates the object stored in this backend.
OdbStreamWriter CreateStream()
Creates a stream that will be saved to database when closed and/or disposed. a stream writer that sho...
static bool TryParse(string input, out ObjectId result)
Tries to parse an ObjectId from a string.
virtual int GetSize(ObjectId objectId)
Requests that this backend read an object's length (but not its contents). The ObjectId.The object size.