예제 #1
0
        /// <summary>
        /// Start a transaction
        /// </summary>
        public void StartTransaction()
        {
            try
            {
                CheckClosed();
                transactionLevel++;

                if (transactionLevel == 1)
                {
                    if (streamsChangedDuringTransaction.Count > 0)
                    {
                        throw new StorageException("At the begining of transaction there should be no changed streams");
                    }

                    NotifyTransactionChanging(TransactionStateChangeType.Start);

                    MasterStream.StartTransaction();

                    if (transactionStream != null)
                    {
                        // Make a list of extents that doesn't need to be backed up
                        IEnumerable <Transactions.Segment> list = FreeSpaceStream != null?FreeSpaceStream.Segments.Select(x => new Transactions.Segment(x.DataAreaStart, x.DataAreaSize)) : null;

                        transactionStream.BeginTransaction(list);
                    }

                    NotifyTransactionChanged(TransactionStateChangeType.Start);
                }
            }
            catch
            {
                InternalRollbackTransaction();
                throw;
            }
        }
예제 #2
0
        /// <summary>
        /// Closes the storage
        /// </summary>
        public void Close()
        {
            if (transactionLevel > 0)
            {
                InternalRollbackTransaction();
                throw new StorageException("Unable to close storage while transaction is pending");
            }

            if (!isClosed)
            {
                lock (openedStreams)
                {
                    //cacheCleanupTimer.Dispose();
                    //cacheCleanupTimer = null;

                    RollbackTransaction();

                    // Cache stream table into empty space stream
                    MasterStream.Flush();
                    MasterStream.Close();
                    openedStreams.Clear();
                    streamsChangedDuringTransaction.Clear();
                    isClosed = true;
                }
            }
        }
예제 #3
0
        private void InternalRollbackTransaction()
        {
            if (transactionLevel > 0)
            {
                // Remove opened streams created during transaction
                lock (openedStreams)
                {
                    foreach (Guid streamId in streamsCreatedDuringTransaction)
                    {
                        WeakReference <StorageStream> reference;
                        if (openedStreams.TryGetValue(streamId, out reference))
                        {
                            StorageStream tmpStream;
                            if (reference.TryGetTarget(out tmpStream))
                            {
                                if (tmpStream != null)
                                {
                                    tmpStream.InternalClose();
                                }
                            }

                            openedStreams.Remove(streamId);
                        }
                    }
                    streamsCreatedDuringTransaction.Clear();

                    // Rollback data
                    transactionStream.RollbackTransaction();
                    MasterStream.RollbackTransaction();
                    streamsChangedDuringTransaction.Clear();

                    // Rollback changes in stream table
                    streamTableStream.ReloadSegmentsOnRollback(streamTableStreamMetadata);
                    streamTable.RollbackTransaction();

                    // Reload segments in system and opened streams because segments has changed
                    foreach (var item in openedStreams.Values.ToList())
                    {
                        StorageStream tmpStream;
                        if (item.TryGetTarget(out tmpStream))
                        {
                            if (streamTable.Contains(tmpStream.StreamId))
                            {
                                StorageStreamMetadata tmpStreamMetadata = streamTable.Get(tmpStream.StreamId);
                                tmpStream.ReloadSegmentsOnRollback(tmpStreamMetadata);
                            }
                            else
                            {
                                tmpStream.InternalClose();
                            }
                        }
                    }

                    // Reload empty space segments
                    var freeSpaceStreamMetadata = streamTable.Get(SystemStreamId.EmptySpace);
                    FreeSpaceStream.ReloadSegmentsOnRollback(freeSpaceStreamMetadata);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Trim the master file to the location where data ends
        /// </summary>
        public void TrimStorage()
        {
            Segment lastSegment = FreeSpaceStream.Segments.SingleOrDefault(x => !x.NextLocation.HasValue);

            if (lastSegment != null)
            {
                MasterStream.SetLength(lastSegment.DataAreaStart);
            }
        }
예제 #5
0
        /// <summary>
        /// Commits a transaction
        /// </summary>
        public void CommitTransaction()
        {
            try
            {
                CheckClosed();
                if (transactionLevel == 1)
                {
                    NotifyTransactionChanging(TransactionStateChangeType.Commit);

                    SaveChanges();
                    if (transactionStream != null)
                    {
                        transactionStream.EndTransaction();
                    }

                    streamsCreatedDuringTransaction.Clear();
                    MasterStream.Flush();
                    MasterStream.CommitTransaction();
                    Statistics.TransactionsCommited++;
                }

                if (transactionLevel > 0)
                {
                    transactionLevel--;

                    if (transactionLevel == 0)
                    {
                        NotifyTransactionChanged(TransactionStateChangeType.Commit);
                    }
                }
            }
            catch
            {
                InternalRollbackTransaction();
                throw;
            }
        }