public void OverwriteColumnStream() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; var data = Any.BytesOfLength(1024); var newData = Any.BytesOfLength(128); const int Offset = 10; using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(data, 0, data.Length); stream.Position = 0; stream.Seek(Offset, SeekOrigin.Current); stream.Write(newData, 0, newData.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { Assert.AreEqual(data.Length, stream.Length); var retrieved = new byte[data.Length]; var expected = new byte[data.Length]; Array.Copy(data, 0, expected, 0, data.Length); Array.Copy(newData, 0, expected, Offset, newData.Length); Assert.AreEqual(retrieved.Length, stream.Read(retrieved, 0, retrieved.Length)); CollectionAssert.AreEqual(expected, retrieved); } }
public void ShrinkColumnStream() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; const int Length = 1345; var data = Any.BytesOfLength(Length); using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(data, 0, data.Length); stream.Write(data, 0, data.Length); Assert.AreEqual(Length * 2, stream.Length); stream.SetLength(Length); Assert.AreEqual(Length, stream.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { Assert.AreEqual(Length, stream.Length); var buffer = new byte[Length]; stream.Read(buffer, 0, buffer.Length); CollectionAssert.AreEqual(data, buffer); } }
public void ExtendingColumnStream() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; var data = Any.BytesOfLength(4096); using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { // Write some of the data, rewind a bit and then overwrite the // last few bytes and append some more data stream.Write(data, 0, data.Length - 10); stream.Seek(-10, SeekOrigin.End); stream.Write(data, data.Length - 20, 20); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { Assert.AreEqual(data.Length, stream.Length); var retrieved = new byte[data.Length]; Assert.AreEqual(retrieved.Length, stream.Read(retrieved, 0, retrieved.Length)); CollectionAssert.AreEqual(data, retrieved); } }
public void GrowColumnStreamByWritingPastEnd() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; const int Length = 1345; const int Position = 1500; var data = Any.BytesOfLength(Length); using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Position = Position; stream.Write(data, 0, data.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { Assert.AreEqual(Length + Position, stream.Length); var expected = new byte[Length + Position]; var actual = new byte[Length + Position]; Array.Copy(data, 0, expected, Position, Length); Assert.AreEqual(Length + Position, stream.Read(actual, 0, actual.Length)); CollectionAssert.AreEqual(expected, actual); } }
public void ReadReturnsNumberOfBytesRead() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; var data = Any.BytesOfLength(1024); using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(data, 0, data.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { var retrieved = new byte[data.Length]; stream.Seek(-1, SeekOrigin.End); Assert.AreEqual(1, stream.Read(retrieved, 0, retrieved.Length)); Assert.AreEqual(data[data.Length - 1], retrieved[0]); } }
public void ReadAtNonZeroOffset() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; var data = Any.BytesOfLength(1024); using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(data, 0, data.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { var retrieved = new byte[data.Length * 2]; stream.Read(retrieved, data.Length, data.Length); for (int i = data.Length; i < retrieved.Length; ++i) { Assert.AreEqual(retrieved[i], data[i - data.Length]); } } }
public void WriteThrowsExceptionWhenBufferIsNull() { using (var t = new Transaction(this.sesid)) using (var u = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(null, 0, 0); } }
public void WriteThrowsExceptionWhenNumberOfBytesIsTooLarge() { using (var t = new Transaction(this.sesid)) using (var u = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { var buffer = new byte[10]; stream.Write(buffer, 1, buffer.Length); } }
public void WriteThrowsExceptionWhenBufferOffsetIsNegative() { using (var t = new Transaction(this.sesid)) using (var u = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { var buffer = new byte[10]; stream.Write(buffer, -1, 1); } }
public void VerifySeekFromEndThrowsExceptionOnOverflow() { using (var t = new Transaction(this.sesid)) using (var u = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(new byte[10], 0, 10); try { stream.Seek(Int64.MaxValue, SeekOrigin.End); Assert.Fail("Expected OverflowException"); } catch (OverflowException) { // expected } } }
public void GetBlockBoundsTest() { const int blockSize = 8192; var data = Factory.CreateDoubleChunk(blockSize / sizeof(DoubleEntry) * 21); var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var stream = new ColumnStream <DoubleEntry>( new MinotaurMemoryStream(), new VoidCodec <DoubleEntry>(), blockSize); var pdata = (byte *)handle.AddrOfPinnedObject(); stream.Write(pdata, data.Length * sizeof(DoubleEntry)); stream.Flush(); stream.Reset(); var blocks = stream.ReadBlockInfos(); Assert.AreEqual(21, blocks.Count); for (int i = 0, j = 0; i < blocks.Count; i++) { Assert.AreEqual(blocks[i].PayloadLength, blockSize); Assert.AreEqual(blocks[i].DataLength, blockSize / sizeof(DoubleEntry)); Assert.AreEqual(blocks[i].ShellSize, sizeof(PayloadHeader) + 2 * sizeof(DoubleEntry) + sizeof(byte)); Assert.AreEqual(blocks[i].Version, 1); Assert.AreEqual(blocks[i].FirstValue.ticks, data[j].ticks); Assert.AreEqual(blocks[i].FirstValue.value, data[j].value); j += blocks[i].DataLength; Assert.AreEqual(blocks[i].LastValue.ticks, data[j - 1].ticks); Assert.AreEqual(blocks[i].LastValue.value, data[j - 1].value); } } finally { handle.Free(); } }
public void WritePastMaxSizeThrowsException() { var data = new byte[256]; using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Seek(Int32.MaxValue - 10, SeekOrigin.Begin); try { stream.Write(data, 0, data.Length); Assert.Fail("Expected OverflowException"); } catch (OverflowException) { // expected } } }
public void SetColumnStreamPosition() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Write(Any.BytesOfLength(1024), 0, 1024); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { stream.Position = 10; Assert.AreEqual(10, stream.Position); } }
public void SetColumnStreamToZeroLength() { var bookmark = new byte[SystemParameters.BookmarkMost]; int bookmarkSize; using (var transaction = new Transaction(this.sesid)) using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert)) using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText)) { byte[] data = Any.Bytes; stream.Write(data, 0, data.Length); stream.SetLength(0); Assert.AreEqual(0, stream.Length); update.Save(bookmark, bookmark.Length, out bookmarkSize); transaction.Commit(CommitTransactionGrbit.LazyFlush); } Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize); CollectionAssert.AreEqual(new byte[0], Api.RetrieveColumn(this.sesid, this.tableid, this.columnidLongText)); }
/// <summary> /// Сохранить файл. /// </summary> /// <param name="blob">Файл.</param> /// <param name="token">Токен отмены.</param> /// <returns>GUID файла.</returns> public async Task <BlobId> SaveBlob(InputBlob blob, CancellationToken token) { if (blob.BlobStream == null) { // ReSharper disable once NotResolvedInText throw new ArgumentNullException("blob.BlobStream"); } if (blob.UniqueName == null) { // ReSharper disable once NotResolvedInText throw new ArgumentNullException("blob.UniqueName"); } CheckModuleReady(); await WaitForTablesInitialize(); return(await OpenSessionAsync(async session => { token.ThrowIfCancellationRequested(); byte[] buffer = new byte[64 * 1024]; int blobId = 0; bool isFilestream = false; byte[] bookmark = null; long tmpLength = 0; try { using (var tmpStream = await DumpToTempStream(blob.BlobStream, blob.MaxSize, buffer, token)) { var frs = await session.RunInTransaction(() => { using (var table = OpenBlobsTable(session, OpenTableGrbit.None)) { var sid = table.Session; // ReSharper disable once AccessToDisposedClosure var isFile = tmpStream.Length >= FileStreamSize; var updateData = new BlobsTable.ViewValues.FullRowUpdate() { Name = blob.UniqueName, Category = blob.Category, CreatedDate = DateTime.Now, Data = new byte[0], Length = 0, ReferenceId = blob.ReferenceId, IsCompleted = false, IsFilestream = isFile }; using (var update = table.Insert.CreateUpdate()) { var bid = table.Columns.Id_AutoincrementValue; table.Insert.FullRowUpdate.Set(ref updateData); table.Insert.SaveUpdateWithBookmark(update, out var bmark); // ReSharper disable once AccessToDisposedClosure return (true, new SaveId() { Id = bid, Bookmark = bmark, IsFilestream = isFile }); } } }); blobId = frs.Id; bookmark = frs.Bookmark; isFilestream = frs.IsFilestream; if (isFilestream) { tmpStream.MoveAfterClose(_filestreamFolder, BlobFileName(blobId)); } else { tmpStream.Position = 0; long counter = 0; do { var counter2 = counter; var sz = await tmpStream.ReadAsync(buffer, 0, buffer.Length, token); if (sz <= 0) { break; } await session.RunInTransaction(() => { token.ThrowIfCancellationRequested(); using (var table = OpenBlobsTable(session, OpenTableGrbit.None)) { var sid = table.Session; if (!table.TryGotoBookmark(bookmark)) { throw new BlobException($"Неверные данные в таблице {BlobsTableName}, ID={blobId}, pos={counter2}"); } using (var update = table.Update.CreateUpdate()) { using (var str = new ColumnStream(sid, table, table.GetColumnid(BlobsTable.Column.Data))) { str.Seek(0, SeekOrigin.End); str.Write(buffer, 0, sz); if (str.Length > MaxFileSize) { throw new BlobException("Размер сохраняемого файла больше допустимого"); } } update.Save(); } return true; } }, 1.5); counter += sz; if (sz < buffer.Length) { break; } } while (true); } tmpLength = tmpStream.Length; if (blob.RememberTempFile) { _tempPaths[new BlobId() { Id = blobId }] = tmpStream.TempFilePath; } } await session.RunInTransaction(() => { using (var table = OpenBlobsTable(session, OpenTableGrbit.None)) { if (!table.TryGotoBookmark(bookmark)) { throw new BlobException($"Неверные данные в таблице {BlobsTableName}, ID={blobId}"); } var size = tmpLength; table.Update.UpdateAsCompletedUpdate(new BlobsTable.ViewValues.CompletedUpdate() { Length = (long)size, IsCompleted = true }); return true; } }, 1.5); } catch (OperationCanceledException) { if (bookmark == null) { throw; } try { await session.RunInTransaction(() => { using (var table = OpenBlobsTable(session, OpenTableGrbit.None)) { if (table.TryGotoBookmark(bookmark)) { table.DeleteCurrentRow(); } return true; } }, 1.5); } catch (Exception e2) { // ReSharper disable once PossibleIntendedRethrow throw e2; } throw; } catch (Exception e) { if (bookmark == null) { throw; } try { await session.RunInTransaction(() => { using (var table = OpenBlobsTable(session, OpenTableGrbit.None)) { if (table.TryGotoBookmark(bookmark)) { table.DeleteCurrentRow(); } return true; } }, 1.5); } catch (Exception e2) { throw new AggregateException(e, e2); } throw; } return new BlobId() { Id = blobId }; })); }
public void ReadWriteWorkflowTest() { var ms = new MinotaurMemoryStream(); const int bufferSize = 1024; var wrapSize = sizeof(PayloadHeader) + sizeof(byte) * 2 + sizeof(byte); var bufferSizeWithoutWrapSize = bufferSize - wrapSize; const int fullBufferSize = bufferSize * 5 + 512; var writeBuffer = new UnsafeBuffer(fullBufferSize); var readBuffer = new UnsafeBuffer(fullBufferSize); writeBuffer.SetAll(2); readBuffer.SetAll(0); var stream = new ColumnStream <byte>(ms, new VoidCodec <byte>(), bufferSize); // 1. Test write less than buffer var write = 100; var wrote = stream.Write(writeBuffer.Ptr, write); wrote.Check(write); ms.Position.Check(0); stream.Flush(); ms.Position.Check(write + wrapSize); ReadWf(stream, readBuffer, 2, write); // 2. Test write more than buffer writeBuffer.SetAll(2); stream.Reset(); ms.SetLength(0); write = bufferSize * 4 + 512; wrote = stream.Write(writeBuffer.Ptr, write); wrote.Check(write); ms.Position.Check((bufferSize + wrapSize) * 4); stream.Flush(); ms.Position.Check(write + 5 * wrapSize); ReadWf(stream, readBuffer, 2, write); // 2. Test write exactly buffer size writeBuffer.SetAllUntil(bufferSizeWithoutWrapSize, 2); stream.Reset(); ms.SetLength(0); write = bufferSize; wrote = stream.Write(writeBuffer.Ptr, write); wrote.Check(write); ms.Position.Check(bufferSize + wrapSize); stream.Flush(); ms.Position.Check(bufferSize + wrapSize); stream.Reset(); ReadWf(stream, readBuffer, 2, write); stream.Dispose(); writeBuffer.Dispose(); readBuffer.Dispose(); }