Beispiel #1
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="transBase">The parent <see cref="BaseTransaction" />.</param>
 /// <param name="position">The <see cref="ILogPosition" /> for the first <see cref="IOperation" /> for this transaction.</param>
 internal Transaction(BaseTransaction transBase, ILogPosition position)
 {
     this.syncLock     = transBase.Manager.SyncRoot;
     this.transBase    = transBase;
     this.position     = position;
     this.isOpen       = true;
     this.resourceData = null;
 }
Beispiel #2
0
        /// <summary>
        /// Reads the operation from the specified position in the log.
        /// </summary>
        /// <param name="resource">The parent <see cref="ITransactedResource" /> responsible for deserializing the operation.</param>
        /// <param name="position">See the <see cref="ILogPosition" />.</param>
        /// <returns>The <see cref="IOperation" /> read from the log.</returns>
        /// <exception cref="TransactionException">Thrown if the log is not open.</exception>
        public IOperation Read(ITransactedResource resource, ILogPosition position)
        {
            using (TimedLock.Lock(syncLock))
            {
                if (!isOpen)
                {
                    throw new TransactionException(NotOpenMsg);
                }

                return(operations[((MemoryLogPosition)position).Index]);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Truncates the log to the position passed.
        /// </summary>
        /// <param name="position">The <see cref="ILogPosition" /> defining where the truncation should occur.</param>
        /// <remarks>
        /// <note>
        /// This property can only be called if the operation log is in <see cref="OperationLogMode.Undo" />
        /// mode.
        /// </note>
        /// <para>
        /// This method is used in combination with the <see cref="Position" /> property to roll
        /// back operations within a base transaction.
        /// </para>
        /// </remarks>
        /// <exception cref="TransactionException">Thrown if the log isn't open or if the mode isn't <see cref="OperationLogMode.Undo" />.</exception>
        public void Truncate(ILogPosition position)
        {
            using (TimedLock.Lock(this))
            {
                if (file == null)
                {
                    throw new TransactionException(ClosedMsg);
                }

                if (mode != OperationLogMode.Undo)
                {
                    throw new TransactionException("Write is available only when the log is in UNDO mode.");
                }

                file.SetLength(((FileLogPosition)position).Position);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Returns the set of <see cref="ILogPosition" /> for each operation from the end of the
        /// log to the <paramref name="position" /> passed, in the reverse order that the operations
        /// were added to the log.
        /// </summary>
        /// <param name="position">The limit position.</param>
        /// <returns>The operation position list.</returns>
        /// <exception cref="ArgumentException">Thrown if the position passed is not valid.</exception>
        /// <exception cref="TransactionException">Thrown if the log is not open or is corrupt.</exception>
        public List <ILogPosition> GetPositionsTo(ILogPosition position)
        {
            var  list = new List <ILogPosition>();
            var  pos  = (FileLogPosition)position;
            long length;
            int  cb;

            using (TimedLock.Lock(this))
            {
                if (file == null)
                {
                    throw new TransactionException(ClosedMsg);
                }

                if (pos.Position < HeaderSize || pos.Position > file.Length)
                {
                    throw new ArgumentException("Invalid log position.", "position");
                }

                length        = file.Length;
                file.Position = pos.Position;

                while (!file.Eof)
                {
                    list.Add(new FileLogPosition(file.Position));

                    if (file.ReadInt32() != Magic)
                    {
                        throw new TransactionException(CorruptMsg);
                    }

                    cb = file.ReadInt32();
                    if (cb < 0 || cb + file.Position > length)
                    {
                        throw new TransactionException(CorruptMsg);
                    }

                    file.Position += cb;
                }
            }

            list.Reverse();
            return(list);
        }
Beispiel #5
0
        /// <summary>
        /// Returns the set of <see cref="ILogPosition" />s for each operation from the end of the
        /// log to the <paramref name="position" /> passed, in the reverse order that the operations
        /// were added to the log.
        /// </summary>
        /// <param name="position">The limit position.</param>
        /// <returns>The operation position list.</returns>
        /// <exception cref="TransactionException">Thrown if the log is not open.</exception>
        public List <ILogPosition> GetPositionsTo(ILogPosition position)
        {
            int index = ((MemoryLogPosition)position).Index;
            List <ILogPosition> positions;

            using (TimedLock.Lock(syncLock))
            {
                if (!isOpen)
                {
                    throw new TransactionException(NotOpenMsg);
                }

                positions = new List <ILogPosition>(operations.Count - index);
                for (int i = operations.Count - 1; i >= index; i--)
                {
                    positions.Add(new MemoryLogPosition(i));
                }

                return(positions);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Reads the operation from the specified position in the log.
        /// </summary>
        /// <param name="resource">The parent <see cref="ITransactedResource" /> responsible for deserializing the operation.</param>
        /// <param name="position">See the <see cref="ILogPosition" />.</param>
        /// <returns>The <see cref="IOperation" /> read from the log.</returns>
        public IOperation Read(ITransactedResource resource, ILogPosition position)
        {
            int        cb;
            long       recEndPos;
            string     description;
            IOperation operation;

            using (TimedLock.Lock(this))
            {
                if (file == null)
                {
                    throw new TransactionException(ClosedMsg);
                }

                file.Position = ((FileLogPosition)position).Position;

                if (file.ReadInt32() != Magic)
                {
                    throw new TransactionException(CorruptMsg);
                }

                cb = file.ReadInt32();
                if (cb <= 0 || cb + file.Position > file.Length)
                {
                    throw new TransactionException(CorruptMsg);
                }

                recEndPos   = file.Position + cb;
                description = file.ReadString32();
                operation   = resource.ReadOperation(file);

                if (file.Position != recEndPos)
                {
                    SysLog.LogWarning("ITransactedResource.ReadOperation() returned with an unexpected stream position.");
                    file.Position = recEndPos;
                }

                return(operation);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Truncates the log to the position passed.
        /// </summary>
        /// <param name="position">The <see cref="ILogPosition" /> defining where the truncation should occur.</param>
        /// <remarks>
        /// <note>
        /// This property can only be called if the operation log is in <see cref="OperationLogMode.Undo" />
        /// mode.
        /// </note>
        /// <para>
        /// This method is used in combination with the <see cref="Position" /> property to roll
        /// back operations within a base transaction.
        /// </para>
        /// </remarks>
        /// <exception cref="TransactionException">Thrown if the log isn't open or if the mode isn't <see cref="OperationLogMode.Undo" />.</exception>
        public void Truncate(ILogPosition position)
        {
            using (TimedLock.Lock(syncLock))
            {
                if (!isOpen)
                {
                    throw new TransactionException(NotOpenMsg);
                }

                if (mode != OperationLogMode.Undo)
                {
                    throw new TransactionException("Write is available only when the log is in UNDO mode.");
                }

                var pos = (MemoryLogPosition)position;

                if (pos.Index < 0 || pos.Index > operations.Count)
                {
                    throw new TransactionException("Invalid operation log position [length={0} pos={1}].", operations.Count, pos.Index);
                }

                operations.RemoveRange(pos.Index, operations.Count - pos.Index);
            }
        }