public void InMemDb_Core_ChunkUpload_NewFile() { Test(async() => { var root = CreateTestRoot(); var file = new File(root) { Name = "File1.txt" }; file.Binary.ContentType = "application/octet-stream"; //file.Binary.FileName = "File1.txt"; file.Save(); var chunks = new[] { new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, new byte[] { 4, 4 } }; var chunkSize = chunks[0].Length; // START CHUNK var versionId = file.VersionId; var propertyTypeId = PropertyType.GetByName("Binary").Id; var fullSize = 50L; var token = await BlobStorage.StartChunkAsync(versionId, propertyTypeId, fullSize, CancellationToken.None) .ConfigureAwait(false); // WRITE CHUNKS for (int i = 0; i < chunks.Length; i++) { var offset = i * chunkSize; var chunk = chunks[i]; await BlobStorage.WriteChunkAsync(versionId, token, chunk, offset, fullSize, CancellationToken.None).ConfigureAwait(false); } // COMMIT CHUNK await BlobStorage.CommitChunkAsync(versionId, propertyTypeId, token, fullSize, null, CancellationToken.None) .ConfigureAwait(false); // ASSERT Cache.Reset(); file = Node.Load <File>(file.Id); var length = Convert.ToInt32(file.Binary.Size); var buffer = new byte[length]; using (var stream = file.Binary.GetStream()) stream.Read(buffer, 0, length); Assert.AreEqual( "11111111111111112222222222222222333333333333333344", new string(buffer.Select(b => (char)(b + '0')).ToArray())); }).GetAwaiter().GetResult(); }
/// <summary> /// This method deletes orphaned rows from the database physically. /// </summary> private static void CleanupFilesDeleteRows() { var deleteCount = 0; try { SnTrace.Database.Write(TRACE_PREFIX + "Cleanup files: deleting rows..."); // keep deleting orphaned binary rows while there are any while (BlobStorage.CleanupFiles()) { deleteCount++; } if (deleteCount > 0) { SnLog.WriteInformation(string.Format("{0} orphaned rows were deleted from the binary table during cleanup.", deleteCount), EventId.RepositoryRuntime); } } catch (Exception ex) { SnLog.WriteWarning("Error in file cleanup background process. " + ex, EventId.RepositoryRuntime); } }
public override int Read(byte[] buffer, int offset, int count) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (offset + count > buffer.Length) { throw new ArgumentException("Offset + count must not be greater than the buffer length."); } if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "The offset must be greater than zero."); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count), "The count must be greater than zero."); } // Calculate the maximum count of the bytes that can be read. // Return immediately if nothing to read. var maximumReadableByteCount = Length - Position; if (maximumReadableByteCount < 1) { return(0); } var realCount = (int)Math.Min(count, maximumReadableByteCount); if (CanInnerBufferHandleReadRequest(realCount)) { Array.Copy(_innerBuffer, (int)Position - _innerBufferFirstPostion, buffer, offset, realCount); } else { _innerBuffer = null; var bytesRead = 0; var bytesStoredInInnerBuffer = 0; while (bytesRead < realCount) { // bytes to load from the db var bytesToReadInThisIteration = (int)Math.Min(this.Length - Position - bytesRead, BlobStorageOptions.BinaryChunkSize); // bytes that we will copy to the buffer of the caller var bytesToStoreInThisIteration = Math.Min(bytesToReadInThisIteration, realCount - bytesRead); // stores the current chunk var tempBuffer = BlobStorage.LoadBinaryFragmentAsync(this.FileId, Position + bytesRead, bytesToReadInThisIteration, CancellationToken.None).GetAwaiter().GetResult(); // first iteration: create inner buffer for caching a part of the stream in memory if (_innerBuffer == null) { _innerBuffer = new byte[GetInnerBufferSize(realCount)]; _innerBufferFirstPostion = Position; } // store a fragment of the data in the inner buffer if possible if (bytesStoredInInnerBuffer < _innerBuffer.Length) { var bytesToStoreInInnerBuffer = Math.Min(bytesToReadInThisIteration, _innerBuffer.Length - bytesStoredInInnerBuffer); Array.Copy(tempBuffer, 0, _innerBuffer, bytesStoredInInnerBuffer, bytesToStoreInInnerBuffer); bytesStoredInInnerBuffer += bytesToStoreInInnerBuffer; } // copy the chunk from the temp buffer to the buffer of the caller Array.Copy(tempBuffer, 0, buffer, bytesRead, bytesToStoreInThisIteration); bytesRead += bytesToReadInThisIteration; } } Position += realCount; return(realCount); }