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);
             }
 }
Exemple #10
0
 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
                 }
             }
 }
Exemple #11
0
        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();
            }
        }
Exemple #12
0
        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
                };
            }));
        }
Exemple #16
0
        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();
        }