/// <inheritdoc/> public virtual ObjectId Write(ObjectId objectId, Stream dataStream, int length, bool forceWrite = false) { if (objectId == ObjectId.Empty) { // This should be avoided using (var digestStream = new DigestStream(Stream.Null)) { dataStream.CopyTo(digestStream); objectId = digestStream.CurrentHash; } dataStream.Seek(0, SeekOrigin.Begin); } string tmpFileName = vfsTempUrl + Guid.NewGuid() + ".tmp"; var url = BuildUrl(vfsRootUrl, objectId); if (!forceWrite && virtualFileProvider.FileExists(url)) { return(objectId); } using (var file = virtualFileProvider.OpenStream(tmpFileName, VirtualFileMode.Create, VirtualFileAccess.Write)) { // TODO: Fast case for NativeStream. However we still need a file implementation of NativeStream. var buffer = new byte[WriteBufferSize]; for (int offset = 0; offset < length; offset += WriteBufferSize) { int blockSize = length - offset; if (blockSize > WriteBufferSize) { blockSize = WriteBufferSize; } dataStream.Read(buffer, 0, blockSize); file.Write(buffer, 0, blockSize); } } MoveToDatabase(tmpFileName, objectId, forceWrite); return(objectId); }
/// <summary> /// Creates a in-memory binary blob as a <see cref="Blob"/> that will also be stored using the active <see cref="IOdbBackend"/>. /// Even if <see cref="Blob"/> is new (not in the ODB), memory will be copied. /// </summary> /// <param name="data">The data.</param> /// <param name="size">The size.</param> /// <returns>The <see cref="Blob"/> containing given data, with its reference count incremented.</returns> public Blob CreateBlob(IntPtr data, int size) { // Generate hash ObjectId objectId; var nativeMemoryStream = new NativeMemoryStream(data, size); using (var digestStream = new DigestStream(Stream.Null)) { nativeMemoryStream.CopyTo(digestStream); objectId = digestStream.CurrentHash; } lock (LoadedBlobs) { var blob = Lookup(objectId); // Blob doesn't exist yet, so let's create it and save it to ODB. if (blob == null) { // Let's go back to beginning of stream after previous hash nativeMemoryStream.Position = 0; // Create blob blob = new Blob(this, objectId, data, size); blob.AddReference(); // Write to disk backendWrite.Write(objectId, nativeMemoryStream, size, false); // Add blob to cache LoadedBlobs.Add(objectId, blob); } return(blob); } }