Пример #1
0
        public void BinaryData_Rollback()
        {
            string text = "Lorem ipsum...";
            File   file = new File(this.TestRoot);
            var    bin  = new BinaryData();

            bin.FileName = "1.txt";
            bin.SetStream(Tools.GetStreamFromString(text));
            file.Binary = bin;
            file.Save();
            int id = file.Id;

            file = Node.Load <File>(id);

            TransactionScope.Begin();
            try
            {
                // Save binary
                file.Binary = null;
                file.Save();
            }
            finally
            {
                // Rollback
                TransactionScope.Rollback();
            }
            file = Node.Load <File>(id);

            Assert.IsNotNull(file.Binary, "#1");
            Assert.IsTrue(file.Binary.Size > 0, "#2");
            Assert.IsTrue(Tools.GetStreamString(file.Binary.GetStream()) == text, "#3");
        }
        /// <summary>
        /// Marks orphaned file records (the ones that do not have a referencing binary record anymore) as Deleted.
        /// </summary>
        public void CleanupFilesSetDeleteFlag()
        {
            var isLocalTransaction = false;

            if (!TransactionScope.IsActive)
            {
                TransactionScope.Begin();
                isLocalTransaction = true;
            }

            try
            {
                using (var proc = new SqlProcedure {
                    CommandText = CleanupFileSetIsdeletedScript, CommandType = CommandType.Text
                })
                {
                    proc.CommandType = CommandType.Text;
                    proc.ExecuteNonQuery();
                }

                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Commit();
                }
            }
            catch (Exception ex)
            {
                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Rollback();
                }

                throw new DataException("Error during setting deleted flag on files.", ex);
            }
        }
Пример #3
0
        private static void RegisterSchema(SchemaEditor origSchema, SchemaEditor newSchema, SchemaWriter schemaWriter)
        {
            using (var op = SnTrace.Database.StartOperation("Write storage schema modifications."))
            {
                // Ensure transaction encapsulation
                bool isLocalTransaction = !TransactionScope.IsActive;
                if (isLocalTransaction)
                {
                    TransactionScope.Begin();
                }
                try
                {
                    List <PropertySet> modifiedPropertySets = new List <PropertySet>();
                    schemaWriter.Open();
                    WriteSchemaModifications(origSchema, newSchema, schemaWriter, modifiedPropertySets);
                    foreach (PropertySet modifiedPropertySet in modifiedPropertySets)
                    {
                        NodeTypeDependency.FireChanged(modifiedPropertySet.Id);
                    }
                    schemaWriter.Close();
                    if (isLocalTransaction)
                    {
                        TransactionScope.Commit();
                    }
                    ActiveSchema.Reset();
                    op.Successful = true;
                }
                catch (Exception ex)
                {
                    SnLog.WriteException(ex, null, EventId.RepositoryRuntime);
                    throw new SchemaEditorCommandException("Error during schema registration.", ex);
                }
                finally
                {
                    IDisposable unmanagedWriter = schemaWriter as IDisposable;
                    if (unmanagedWriter != null)
                    {
                        unmanagedWriter.Dispose();
                    }
                    try
                    {
                        if (isLocalTransaction && TransactionScope.IsActive)
                        {
                            TransactionScope.Rollback();
                        }
                    }
                    catch (Exception ex2)
                    {
                        // This catch block will handle any errors that may have occurred
                        // on the server that would cause the rollback to fail, such as
                        // a closed connection (MSDN).
                        const string msg = "Error during schema transaction rollback.";
                        SnLog.WriteException(ex2, msg, EventId.RepositoryRuntime);

                        throw new SchemaEditorCommandException(msg, ex2);
                    }
                }
            }
        }
 public void TransactionScope_IsActive()
 {
     Test(() =>
     {
         TransactionScope.Begin();
         Assert.AreEqual(true, TransactionScope.IsActive);
         TransactionScope.Rollback();
     });
 }
 public void TransactionScope_IsolationLevel_ValueTest1()
 {
     Test(() =>
     {
         TransactionScope.Begin(IsolationLevel.Serializable);
         Assert.AreEqual(IsolationLevel.Serializable, TransactionScope.IsolationLevel);
         TransactionScope.Rollback();
     });
 }
 public void TransactionScope_IsolationLevel()
 {
     Test(() =>
     {
         TransactionScope.Begin();
         Assert.AreEqual(IsolationLevel.ReadCommitted, TransactionScope.IsolationLevel);
         TransactionScope.Rollback();
     });
 }
        /// <summary>
        /// Finalizes a chunked save operation.
        /// </summary>
        /// <param name="versionId">Content version id.</param>
        /// <param name="propertyTypeId">Binary property type id.</param>
        /// <param name="fileId">File identifier.</param>
        /// <param name="fullSize">Full size (stream length) of the binary value.</param>
        /// <param name="source">Binary data containing metadata (e.g. content type).</param>
        public void CommitChunk(int versionId, int propertyTypeId, int fileId, long fullSize, BinaryDataValue source = null)
        {
            // start a new transaction here if needed
            var isLocalTransaction = !TransactionScope.IsActive;

            if (isLocalTransaction)
            {
                TransactionScope.Begin();
            }

            try
            {
                // commit the process: set the final full size and checksum
                using (var cmd = new SqlProcedure {
                    CommandText = CommitChunkScript, CommandType = CommandType.Text
                })
                {
                    cmd.Parameters.Add("@FileId", SqlDbType.Int).Value            = fileId;
                    cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value         = versionId;
                    cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value    = propertyTypeId;
                    cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value           = fullSize;
                    cmd.Parameters.Add("@Checksum", SqlDbType.VarChar, 200).Value = DBNull.Value;

                    cmd.Parameters.Add("@ContentType", SqlDbType.NVarChar, 50).Value = source != null ? source.ContentType : string.Empty;
                    cmd.Parameters.Add("@FileNameWithoutExtension", SqlDbType.NVarChar, 450).Value = source != null
                        ? source.FileName.FileNameWithoutExtension == null
                            ? DBNull.Value
                            : (object)source.FileName.FileNameWithoutExtension
                        : DBNull.Value;

                    cmd.Parameters.Add("@Extension", SqlDbType.NVarChar, 50).Value = source != null?ValidateExtension(source.FileName.Extension) : string.Empty;

                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                // rollback the transaction if it was opened locally
                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Rollback();
                }

                throw new DataException("Error during committing binary chunk to file stream.", ex);
            }
            finally
            {
                // commit the transaction if it was opened locally
                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Commit();
                }
            }
        }
Пример #8
0
 public void TransactionScope_Begin_AlreadyActive()
 {
     try
     {
         TransactionScope.Begin();
         TransactionScope.Begin();
     }
     finally
     {
         TransactionScope.Rollback();
     }
 }
Пример #9
0
        /// <summary>
        /// Creates a new SnTransaction object and starts a db transaction if the
        /// TransactionScope is not yet active. Call this in a 'using' statement.
        /// </summary>
        /// <param name="isolationLevel">Transaction isolation level.</param>
        /// <param name="timeout">Timeout for the transaction.</param>
        /// <returns>A disposable SnTransaction object.</returns>
        public static SnTransaction Begin(IsolationLevel?isolationLevel = null, TimeSpan?timeout = null)
        {
            var tran = new SnTransaction
            {
                _isLocalTransaction = !TransactionScope.IsActive
            };

            if (tran._isLocalTransaction)
            {
                TransactionScope.Begin(
                    isolationLevel ?? IsolationLevel.ReadCommitted,
                    timeout ?? TimeSpan.FromSeconds(Configuration.Data.TransactionTimeout));
            }

            return(tran);
        }
Пример #10
0
        public void TransactionScope_Commit_UseCase1()
        {
            string name = "CommitTest-" + Guid.NewGuid().ToString();

            AddPathToDelete("/Root/" + name);

            TransactionScope.Begin();

            var folder = new Folder(Repository.Root);

            folder.Name = name;
            folder.Save();

            TransactionScope.Commit();

            folder = (Folder)Node.LoadNode(folder.Id);
            Assert.IsNotNull(folder);
            Assert.AreEqual(name, folder.Name);
        }
        public void TransactionScope_Commit_UseCase1()
        {
            Test(() =>
            {
                var name = "CommitTest-1";

                TransactionScope.Begin();

                var folder  = new Folder(Repository.Root);
                folder.Name = name;
                folder.Save();

                TransactionScope.Commit();

                folder = (Folder)Node.LoadNode(folder.Id);
                Assert.IsNotNull(folder);
                Assert.AreEqual(name, folder.Name);
            });
        }
Пример #12
0
 private void ExecuteScripts(List <StringBuilder> scripts)
 {
     using (var traceOperation = Logger.TraceOperation("Execute storage schema scripts."))
     {
         // Ensure transaction encapsulation
         bool isLocalTransaction = !TransactionScope.IsActive;
         if (isLocalTransaction)
         {
             TransactionScope.Begin();
         }
         try
         {
             if (_slotsToReset.Count > 0)
             {
                 StringBuilder sb = new StringBuilder();
                 scripts.Insert(0, sb);
                 WriteSlotsToResetScripts(sb, _slotsToReset);
             }
             foreach (StringBuilder script in scripts)
             {
                 using (var proc = new SqlProcedure {
                     CommandText = script.ToString(), CommandType = CommandType.Text
                 })
                 {
                     proc.ExecuteNonQuery();
                 }
             }
             if (isLocalTransaction)
             {
                 TransactionScope.Commit();
             }
             traceOperation.IsSuccessful = true;
         }
         finally
         {
             if (isLocalTransaction && TransactionScope.IsActive)
             {
                 TransactionScope.Rollback();
             }
         }
     }
 }
Пример #13
0
 private static void RegisterSchema(SchemaEditor origSchema, SchemaEditor newSchema, SchemaWriter schemaWriter)
 {
     using (var traceOperation = Logger.TraceOperation("Write storage schema modifications."))
     {
         // Ensure transaction encapsulation
         bool isLocalTransaction = !TransactionScope.IsActive;
         if (isLocalTransaction)
         {
             TransactionScope.Begin();
         }
         try
         {
             List <PropertySet> modifiedPropertySets = new List <PropertySet>();
             schemaWriter.Open();
             WriteSchemaModifications(origSchema, newSchema, schemaWriter, modifiedPropertySets);
             foreach (PropertySet modifiedPropertySet in modifiedPropertySets)
             {
                 NodeTypeDependency.FireChanged(modifiedPropertySet.Id);
             }
             schemaWriter.Close();
             if (isLocalTransaction)
             {
                 TransactionScope.Commit();
             }
             ActiveSchema.Reset();
             traceOperation.IsSuccessful = true;
         }
         finally
         {
             IDisposable unmanagedWriter = schemaWriter as IDisposable;
             if (unmanagedWriter != null)
             {
                 unmanagedWriter.Dispose();
             }
             if (isLocalTransaction && TransactionScope.IsActive)
             {
                 TransactionScope.Rollback();
             }
         }
     }
 }
        //[TestMethod]
        public void TransactionScope_Rollback_UseCase1()
        {
            Test(() =>
            {
                var name = "RollbackTest-1";

                var folder  = new Folder(Repository.Root);
                folder.Name = name;
                TransactionScope.Begin();

                folder.Save();
                int id = folder.Id;
                Assert.AreNotEqual(0, id);

                TransactionScope.Rollback();

                Assert.AreEqual(0, folder.Id, "Node.Id must be set back to 0 after a rollback event.");
                folder = (Folder)Node.LoadNode(id);
                Assert.IsNull(folder);
            });
        }
Пример #15
0
        //[TestMethod()]
        public void TransactionScope_Rollback_UseCase1()
        {
            string name = "RollbackTest-" + Guid.NewGuid().ToString();

            AddPathToDelete("/Root/" + name);

            var folder = new Folder(Repository.Root);

            folder.Name = name;
            TransactionScope.Begin();

            folder.Save();
            int id = folder.Id;

            Assert.AreNotEqual(0, id);

            TransactionScope.Rollback();

            Assert.AreEqual(0, folder.Id, "Node.Id must be set back to 0 after a rollback event.");
            folder = (Folder)Node.LoadNode(id);
            Assert.IsNull(folder);
        }
Пример #16
0
        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 isLocalTransaction = false;
            var realCount          = (int)Math.Min(count, maximumReadableByteCount);

            if (CanInnerBufferHandleReadRequest(realCount))
            {
                Array.Copy(_innerBuffer, Position - _innerBufferFirstPostion, buffer, offset, realCount);
            }
            else
            {
                if (!TransactionScope.IsActive)
                {
                    // make sure we do not use an obsolete value
                    FileStreamData = null;

                    // Start a new transaction here to serve the needs of the SqlFileStream type.
                    TransactionScope.Begin();
                    isLocalTransaction = true;
                }

                try
                {
                    // Load transaction data for SqlFilestream. If this is not a local transaction,
                    // than we will be able to use this data in the future if the client calls
                    // the Read method multiple times and will not have to execute SQL queries
                    // every time.
                    var ctx = BlobStorageBase.GetBlobStorageContext(this.FileId);
                    if (ctx != null)
                    {
                        if (ctx.Provider == BlobStorageBase.BuiltInProvider)
                        {
                            FileStreamData = ((SqlClient.BuiltinBlobProviderData)ctx.BlobProviderData).FileStreamData;
                        }
                    }
                    if (FileStreamData == null)
                    {
                        throw new InvalidOperationException("Transaction data and file path could not be retrieved for SqlFilestream");
                    }

                    using (var fs = new SqlFileStream(FileStreamData.Path, FileStreamData.TransactionContext, FileAccess.Read, FileOptions.SequentialScan, 0))
                    {
                        fs.Seek(Position, SeekOrigin.Begin);

                        _innerBuffer = null;

                        var bytesRead = 0;
                        var bytesStoredInInnerBuffer = 0;

                        while (bytesRead < realCount)
                        {
                            var bytesToReadInThisIteration  = (int)Math.Min(this.Length - Position - bytesRead, BlobStorage.BinaryChunkSize);
                            var bytesToStoreInThisIteration = Math.Min(bytesToReadInThisIteration, realCount - bytesRead);
                            var tempBuffer = new byte[bytesToReadInThisIteration];

                            // copy the bytes from the file stream to the temp buffer
                            // (it is possible that we loaded a lot more bytes than the client requested)
                            fs.Read(tempBuffer, 0, bytesToReadInThisIteration);

                            // 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;
                        }
                    }
                }
                catch
                {
                    // ReSharper disable once InvertIf
                    if (isLocalTransaction && TransactionScope.IsActive)
                    {
                        TransactionScope.Rollback();

                        // cleanup
                        isLocalTransaction = false;
                        FileStreamData     = null;
                    }
                    throw;
                }
                finally
                {
                    if (isLocalTransaction && TransactionScope.IsActive)
                    {
                        TransactionScope.Commit();

                        // Set filestream data to null as this was a local transaction and we cannot use it anymore
                        FileStreamData = null;
                    }
                }
            }

            Position += realCount;

            return(realCount);
        }
Пример #17
0
        /// <summary>
        /// Starts a chunked save operation on an existing content. It does not write any binary data
        /// to the storage, it only makes prerequisite operations - e.g. allocates a new slot in the storage.
        /// </summary>
        /// <param name="blobProvider">Blob storage provider.</param>
        /// <param name="versionId">Content version id.</param>
        /// <param name="propertyTypeId">Binary property type id.</param>
        /// <param name="fullSize">Full size (stream length) of the binary value.</param>
        /// <returns>A token containing all the information (db record ids) that identify a single entry in the blob storage.</returns>
        public string StartChunk(IBlobProvider blobProvider, int versionId, int propertyTypeId, long fullSize)
        {
            var isLocalTransaction = !TransactionScope.IsActive;

            if (isLocalTransaction)
            {
                TransactionScope.Begin();
            }

            var ctx = new BlobStorageContext(blobProvider)
            {
                VersionId = versionId, PropertyTypeId = propertyTypeId, FileId = 0, Length = fullSize
            };
            string blobProviderName = null;
            string blobProviderData = null;

            if (blobProvider != BlobStorageBase.BuiltInProvider)
            {
                blobProvider.Allocate(ctx);
                blobProviderName = blobProvider.GetType().FullName;
                blobProviderData = BlobStorageContext.SerializeBlobProviderData(ctx.BlobProviderData);
            }

            try
            {
                using (var cmd = new SqlProcedure {
                    CommandText = InsertStagingBinaryScript, CommandType = CommandType.Text
                })
                {
                    cmd.Parameters.Add("@VersionId", SqlDbType.Int).Value              = versionId;
                    cmd.Parameters.Add("@PropertyTypeId", SqlDbType.Int).Value         = propertyTypeId;
                    cmd.Parameters.Add("@Size", SqlDbType.BigInt).Value                = fullSize;
                    cmd.Parameters.Add("@BlobProvider", SqlDbType.NVarChar, 450).Value = blobProviderName != null ? (object)blobProviderName : DBNull.Value;
                    cmd.Parameters.Add("@BlobProviderData", SqlDbType.NVarChar, int.MaxValue).Value = blobProviderData != null ? (object)blobProviderData : DBNull.Value;

                    int binaryPropertyId;
                    int fileId;

                    using (var reader = cmd.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            binaryPropertyId = reader.GetSafeInt32(0);
                            fileId           = reader.GetSafeInt32(1);
                        }
                        else
                        {
                            throw new DataException("File row could not be inserted.");
                        }
                    }

                    ctx.FileId = fileId;

                    return(new ChunkToken
                    {
                        VersionId = versionId,
                        PropertyTypeId = propertyTypeId,
                        BinaryPropertyId = binaryPropertyId,
                        FileId = fileId
                    }.GetToken());
                }
            }
            catch (Exception ex)
            {
                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Rollback();
                }

                throw new DataException("Error during saving binary chunk to SQL Server.", ex);
            }
            finally
            {
                if (isLocalTransaction && TransactionScope.IsActive)
                {
                    TransactionScope.Commit();
                }
            }
        }