4 using System.Collections.Generic;
7 using System.Threading.Tasks;
8 using SiliconStudio.Core.IO;
10 namespace SiliconStudio.Core.Storage
18 private static readonly Dictionary<ObjectId, Blob> LoadedBlobs =
new Dictionary<ObjectId, Blob>();
22 private readonly
IOdbBackend backendRead1, backendRead2, backendWrite;
27 get {
return bundleBackend; }
36 public ObjectDatabase(
string vfsMainUrl,
string indexName =
"index",
string vfsAdditionalUrl = null,
bool loadDefaultBundle =
true)
38 if (vfsMainUrl == null)
throw new ArgumentNullException(
"vfsMainUrl");
44 bool isReadOnly = Platform.Type != PlatformType.Windows;
45 var backend =
new FileOdbBackend(vfsMainUrl, isReadOnly, indexName);
46 AssetIndexMap.Merge(backend.AssetIndexMap);
47 if (backend.IsReadOnly)
49 backendRead1 = backend;
50 if (vfsAdditionalUrl != null)
52 backendWrite = backendRead2 =
new FileOdbBackend(vfsAdditionalUrl,
false);
53 AssetIndexMap.Merge(backendWrite.AssetIndexMap);
58 backendWrite = backendRead1 = backend;
61 AssetIndexMap.WriteableAssetIndexMap = backendWrite.AssetIndexMap;
66 if (loadDefaultBundle)
70 bundleBackend.LoadBundle(
"default", AssetIndexMap).GetAwaiter().GetResult();
72 catch (FileNotFoundException)
80 public void CreateBundle(
ObjectId[] objectIds,
string bundleName,
BundleOdbBackend bundleBackend, ISet<ObjectId> disableCompressionIds, Dictionary<string, ObjectId> indexMap, IList<string> dependencies)
82 if (bundleBackend == null)
83 throw new InvalidOperationException(
"Can't pack files.");
85 if (objectIds.Length == 0)
88 var packUrl = bundleBackend.BundleDirectory + bundleName + BundleOdbBackend.BundleExtension;
91 BundleOdbBackend.CreateBundle(packUrl, backendRead1, objectIds, disableCompressionIds, indexMap, dependencies);
101 return bundleBackend.LoadBundle(bundleName, AssetIndexMap);
111 bundleBackend.UnloadBundle(bundleName, AssetIndexMap);
116 var result = backendRead1.EnumerateObjects();
118 if (bundleBackend != null)
119 result = result.Union(bundleBackend.EnumerateObjects());
121 if (backendRead2 != null)
122 result = result.Union(backendRead2.EnumerateObjects());
129 return backendRead1.EnumerateObjects();
134 if (backendWrite == null)
135 throw new InvalidOperationException(
"Read-only object database.");
137 backendWrite.Delete(objectId);
142 return (bundleBackend != null && bundleBackend.Exists(objectId)) || backendRead1.Exists(objectId) || (backendRead2 != null && backendRead2.Exists(objectId));
147 if (bundleBackend != null && bundleBackend.Exists(objectId))
148 return bundleBackend.GetSize(objectId);
150 if (backendRead1.Exists(objectId))
151 return backendRead1.GetSize(objectId);
153 if (backendRead2 == null)
154 throw new FileNotFoundException();
156 return backendRead2.GetSize(objectId);
161 if (bundleBackend != null && bundleBackend.Exists(objectId))
162 throw new InvalidOperationException();
164 if (backendRead1.Exists(objectId))
165 return backendRead1.GetFilePath(objectId);
167 if (backendRead2 != null && backendRead2.Exists(objectId))
168 return backendRead2.GetFilePath(objectId);
170 return backendWrite.GetFilePath(objectId);
182 if (backendWrite == null)
183 throw new InvalidOperationException(
"Read-only object database.");
195 if (backendWrite == null)
196 throw new InvalidOperationException(
"Read-only object database.");
198 return backendWrite.Write(ObjectId.Empty, stream, (int)stream.Length);
210 if (backendWrite == null)
211 throw new InvalidOperationException(
"Read-only object database.");
213 return backendWrite.Write(objectId, stream, (int)stream.Length, forceWrite);
229 return OpenStreamForRead(objectId, mode, access, share);
232 if (backendWrite == null)
233 throw new InvalidOperationException(
"Read-only object database.");
235 if (backendRead1 == backendWrite)
237 return backendWrite.OpenStream(objectId, mode, access, share);
243 var stream = backendWrite.OpenStream(objectId, mode, access, share);
245 if (streamRead != null)
247 streamRead.CopyTo(stream);
269 if (LoadedBlobs.TryGetValue(objectId, out blob))
276 return OpenStream(objectId);
285 return backendWrite.CreateStream();
303 nativeMemoryStream.CopyTo(digestStream);
304 objectId = digestStream.CurrentHash;
309 var blob = Lookup(objectId);
315 nativeMemoryStream.Position = 0;
318 blob =
new Blob(
this, objectId, data, size);
322 backendWrite.Write(objectId, nativeMemoryStream,
size,
false);
325 LoadedBlobs.Add(objectId, blob);
343 if (!LoadedBlobs.TryGetValue(objectId, out blob))
346 var stream = OpenStream(objectId).ToNativeStream();
351 blob =
new Blob(
this, objectId, stream);
352 LoadedBlobs.Add(objectId, blob);
365 internal void DestroyBlob(
Blob blob)
370 if (!LoadedBlobs.Remove(blob.
ObjectId))
371 throw new InvalidOperationException(
"Destroying a blob not created through ObjectDatabase.CreateBlob.");
377 if (bundleBackend != null && bundleBackend.Exists(objectId))
378 return bundleBackend.OpenStream(objectId, mode, access, share);
380 if (backendRead1.Exists(objectId))
381 return backendRead1.OpenStream(objectId, mode, access, share);
383 if (backendRead2 != null && backendRead2.Exists(objectId))
384 return backendRead2.OpenStream(objectId, mode, access, share);
Stores immutable binary content.
bool Exists(ObjectId objectId)
ObjectId Write(Stream stream, ObjectId objectId, bool forceWrite=false)
Writes the specified data using the active IOdbBackend and a precomputer ObjectId.
Stream Read(ObjectId objectId, bool checkCache=false)
Returns a data stream of the data specified ObjectId.
Asset Index Map implementation which regroups all the asset index maps of every loaded file backend a...
A read-only NativeMemoryStream that will properly keep references on its underlying Blob...
VirtualFileShare
File share capabilities, equivalent of System.IO.FileShare.
int GetSize(ObjectId objectId)
string GetFilePath(ObjectId objectId)
void Delete(ObjectId objectId)
Base class for custom object database backends (ODB).
Gives access to the object database.
Blob Lookup(ObjectId objectId)
Lookups the Blob with the specified ObjectId. Any object returned will have its reference count incre...
Object Database Backend (ODB) implementation using VirtualFileSystem
IEnumerable< ObjectId > EnumerateLooseObjects()
Stream OpenStream(ObjectId objectId, VirtualFileMode mode=VirtualFileMode.Open, VirtualFileAccess access=VirtualFileAccess.Read, VirtualFileShare share=VirtualFileShare.Read)
Opens a stream for the specified ObjectId.
ObjectId ObjectId
Gets the ObjectId.
Object Database Backend (ODB) implementation that bundles multiple chunks into a .bundle files, optionally compressed with LZ4.
VirtualFileAccess
File access equivalent of System.IO.FileAccess.
VirtualFileMode
File mode equivalent of System.IO.FileMode.
void CreateBundle(ObjectId[] objectIds, string bundleName, BundleOdbBackend bundleBackend, ISet< ObjectId > disableCompressionIds, Dictionary< string, ObjectId > indexMap, IList< string > dependencies)
void UnloadBundle(string bundleName)
Loads the specified bundle.
A MemoryStream over a native memory region.
ObjectDatabase(string vfsMainUrl, string indexName="index", string vfsAdditionalUrl=null, bool loadDefaultBundle=true)
Initializes a new instance of the ObjectDatabase class.
OdbStreamWriter CreateStream()
Creates a stream that can then be saved directly in the database using SaveStream.
IEnumerable< ObjectId > EnumerateObjects()
A hash to uniquely identify data.
ObjectId Write(Stream stream)
Writes the specified data using the active IOdbBackend.
Task LoadBundle(string bundleName)
Loads the specified bundle.
Blob CreateBlob(IntPtr data, int size)
Creates a in-memory binary blob as a Blob that will also be stored using the active IOdbBackend...
_In_ size_t _In_ size_t size
ObjectId Write(IntPtr data, int size, bool forceWrite=false)
Writes the specified data using the active IOdbBackend.