void ITransactionNotification.TransactionCompleted(IFileSystemTransaction transaction, bool committed)
 {
     _log.Debug("LongSlaveTransactionManager notified");
     Check.Require(_pendingTransaction != null);
     //do not want to dispose when notified by the transaction because it already knows it itself
     ScrapPendingTransaction(false);;
 }
Example #2
0
        /// <summary>
        ///		Create transaction scope wrapping existing storage transaction.
        /// </summary>
        /// <param name="transactionToUse">
        ///		Transaction to wrap; may be null.
        /// </param>
        /// <param name="dispose">
        ///		Dispose underlying storage transaction at the end of the scope.
        /// </param>
        /// <returns>
        ///		New scope.
        /// </returns>
        public IStorageTransactionScope CreateTransactionScope(IFileSystemTransaction transactionToUse, bool dispose)
        {
            CheckTransactionsSupported();
            Check.DoAssertLambda(transactionToUse == null || transactionToUse is KtmTransaction, () => new ArgumentException("Unknown transaction type"));
            Check.DoAssertLambda(transactionToUse == null || transactionToUse.IsActive, () => new ArgumentException("The transaction is not active"));
            _log.Debug("Creating storage transaction scope from provided transaction");

            return(KtmTransactionScope.Create((KtmTransaction)transactionToUse, dispose));
        }
 public TransactedFileSystemPath(IFileSystemTransaction transaction
                                 , IFileSystemTransactionLog transactionLog
                                 , IFileSystemPath path
                                 )
     : base(path.FullPath)
 {
     this.transaction    = transaction;
     this.transactionLog = transactionLog;
 }
Example #4
0
        /// <summary>
        ///     Detach the underlying transaction from the context. This will ensure that the transaction will not be disposed
        ///     but context handling will not change.
        /// </summary>
        /// <returns>
        ///     <see cref="UnderlyingTransaction"/>
        /// </returns>
        /// <remarks>
        ///     After detaching <see cref="UnderlyingTransaction"/> will return <see langword="null"/>.
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        ///		<see cref="UnderlyingTransaction"/> is <see langword="null"/>
        /// </exception>
        public IFileSystemTransaction DetachTransaction()
        {
            Check.DoCheckOperationValid(_current != null, "No transaction to detach");
            ToBeDisposed = false;
            IFileSystemTransaction retval = _current;

            _current = null;
            return(retval);
        }
 /// <summary>
 ///     Must not throw exceptions
 /// </summary>
 /// <param name="committed">
 ///     Whether transaction was committed successfully.
 /// </param>
 /// <remarks>
 ///		Note that this method may be executed in a concurrent worker thread.
 /// </remarks>
 void ITransactionNotification.TransactionCompleted(IFileSystemTransaction transaction, bool committed)
 {
     if (committed)
     {
         DropUnsavedItems();
     }
     if (_clearDirtyFlagWhenTransactionCompletes)
     {
         _dirty = false;
     }
 }
Example #6
0
 /// <summary>
 ///     Default factory method
 /// </summary>
 /// <param name="repository">
 ///     The repository manager.
 /// </param>
 /// <param name="pendingTransaction">
 ///     Pending transaction to reuse if not <see langword="null"/>.
 /// </param>
 /// <returns>
 /// </returns>
 /// <remarks>
 ///     The most common factory method creates scope catering for the current environment. If pending transaction is provided
 ///     the method acts like <see cref="CreateWrapPending(IRepositoryManager, IFileSystemTransaction)"/>. Otherwise it will act
 ///     as <see cref="StorageTransactionScope(IRepositoryManager, bool)"/>, using repository settings
 ///     (<see cref="repository.Settings.StorageTransactionSettings"/>) to decide if and what kind of transaction to create.
 ///     When wrapping existing pending transaction or when creating slave transaction the scope will be configured not to dispose
 ///     transaction at the end of the scope.
 /// </remarks>
 public static StorageTransactionScope Create(IRepository repository, IFileSystemTransaction pendingTransaction)
 {
     if (pendingTransaction == null)
     {
         // see remarks
         return(new StorageTransactionScope(repository, false));
     }
     else
     {
         return(CreateWrapPending(repository, pendingTransaction));
     }
 }
        /// <summary>
        ///		Scrap pending transaction
        /// </summary>
        /// <param name="dispose">
        ///		Dispose it before throwing away
        /// </param>
        public void ScrapPendingTransaction(bool dispose)
        {
            IFileSystemTransaction pendingTransaction = _pendingTransaction;

            if (pendingTransaction != null)
            {
                if (dispose)
                {
                    pendingTransaction.Dispose();
                }
                _pendingTransaction = null;
            }
        }
Example #8
0
        /// <summary>
        ///		Create scope which will not create its own transaction, but would only pick up existing ambient transaction.
        /// </summary>
        /// <param name="repository">
        ///		Repository
        /// </param>
        /// <param name="pendingTransaction">
        ///     Pending transaction to reuse if not <see langword="null"/>.
        /// </param>
        /// <returns>
        ///		New transaction scope not owning a transaction.
        /// </returns>
        /// <remarks>
        ///
        /// </remarks>
        /// <exception cref="InvalidOperationException">
        ///		Current transactional context is inconsistent with the <paramref name="pendingTransaction"/>.
        /// </exception>
        /// <remarks>
        ///		When <paramref name="pendingTransaction"/> is not null the ambient transaction must be:
        ///			- null
        ///			- equal to <paramref name="pendingTransaction"/>
        ///			- belong to the same master transaction
        ///		Otherwise the "always start new transaction" option must be ON (<see cref="IRepositoryManager.Settings.StorageTransactionSettings"/>).
        ///		If top level scope is created lazy and it is not NULL scope then there is external transaction being used in repository.
        /// </remarks>
        public static StorageTransactionScope CreateLazy(IRepository repository, IFileSystemTransaction pendingTransaction)
        {
            StorageTransactionScope retval;

            if (pendingTransaction == null)
            {
                retval = new StorageTransactionScope(repository: repository, disposeIfSlave: false, okToStartOwnTransaction: false);
                // proxy may have to be a new transaction instance, but slave of an existing managed transaction
                Check.Ensure(!retval.IsTransactionOwner, "Lazy scope must not create and own a transaction, it can only be a proxy to an existing transaction.");
            }
            else
            {
                CheckContextForPendingTransaction(repository: repository, pendingTransaction: pendingTransaction);
                retval = Create(repository, pendingTransaction);
                Check.Ensure(pendingTransaction == retval.UnderlyingTransaction);
            }
            Check.Ensure(!retval.ToBeDisposed, "Lazy scope must not own or dispose underlying transaction");
            return(retval);
        }
Example #9
0
 private static void CheckContextForPendingTransaction(IRepository repository, IFileSystemTransaction pendingTransaction)
 {
     Check.DoCheckOperationValid(
         GetAmbientTransaction(repository) == null ||
         GetAmbientTransaction(repository) == pendingTransaction ||
         IsAlwaysNewTransactionOptionOn(repository) ||
         (
             pendingTransaction.MasterTransaction != null &&
             GetAmbientTransaction(repository).MasterTransaction == pendingTransaction.MasterTransaction
         )
         , StorageResources.ContextInconsistentWithPendingTransaction);
 }
Example #10
0
 /// <summary>
 ///     Factory method for scenario when you already have active transaction which you want to reuse and transaction to live outside
 ///     the code block marked by the scope.
 /// </summary>
 /// <param name="repository">
 ///     The repository.
 /// </param>
 /// <param name="pendingTransaction">
 ///     Transaction to [re]use or null.
 /// </param>
 /// <returns>
 ///     <see cref="StorageTransactionScope"/>
 /// </returns>
 /// <remarks>
 ///     This is a factory method wrapping long living transaction. At the end of the scope transaction will not be
 ///     committed or rolled back or disposed. The context will be changed only if the <paramref name="pendingTransaction"/>
 ///     is not already ambient. At the end of the scope the context will be restored if it had been changed at the start.
 /// </remarks>
 public static StorageTransactionScope CreateWrapPending(IRepository repository, IFileSystemTransaction pendingTransaction)
 {
     CheckContextForPendingTransaction(repository: repository, pendingTransaction: pendingTransaction);
     return(new StorageTransactionScope(repository, pendingTransaction, false));
 }
Example #11
0
 /// <summary>
 ///     Create new instance wrapping the specified transaction instance.
 /// </summary>
 /// <param name="transactionToUse">
 ///     Transaction to wrap in the scope. If null, the scope will clear transaction context.
 /// </param>
 /// <param name="dispose">
 ///     Whether to dispose the <paramref name="transactionToUse"/> when the scope is disposed.
 /// </param>
 protected StorageTransactionScope(IRepository repository, IFileSystemTransaction transactionToUse, bool dispose)
 {
     Initialize(
         repository.ObjectFactory.FileSystemProvider.CreateTransactionScope(transactionToUse, dispose)
         , repository);
 }
Example #12
0
 public void TransactionCompleted(IFileSystemTransaction transaction, bool committed)
 {
     Console.WriteLine("TransactionSubscriber notified");
     Interlocked.Increment(ref _timesNotified);
     _committed = committed;
 }
        /// <summary>
        /// This method should cover all functionality of Txfs.
        /// </summary>
        /// <param name="tx"></param>
        private void Scenario(IFileSystemTransaction tx)
        {
            // Equality

            Assert.AreEqual(this.path.Child("testing.txt"), this.path.Child("testing.txt"));
            Assert.AreNotEqual(this.path.Child("testing.txt"), null);
            Assert.AreNotEqual(this.path.Child("testing.txt"), 425);

            Assert.AreEqual(this.path.FullPath.GetHashCode(), this.path.GetHashCode());

            // Create directory.

            tx.Transact(this.path).CreateDirectory();

            Assert.IsTrue(this.path.IsDirectory());
            Assert.IsTrue(Directory.Exists(this.path.FullPath));

            // Create sub-directory with non-existent parent.

            var nonExistentNestedSubDirectoryPath = this.path.Child("First").Child("Second");

            tx.Transact(nonExistentNestedSubDirectoryPath).CreateDirectory();

            Assert.IsTrue(nonExistentNestedSubDirectoryPath.IsDirectory());
            Assert.IsTrue(Directory.Exists(nonExistentNestedSubDirectoryPath.FullPath));

            // Write JSON file.

            var jsonFilePath = this.path.Child("Test.json");

            tx.Transact(jsonFilePath).WriteJsonFile(new { Hello = "World" });

            Assert.IsTrue(jsonFilePath.IsFile());
            Assert.IsTrue(File.Exists(jsonFilePath.FullPath));
            Assert.AreEqual("{\"Hello\":\"World\"}", jsonFilePath.ReadAllText());

            tx.Transact(jsonFilePath).WriteJsonFile(42);

            Assert.AreEqual(42, jsonFilePath.ReadJsonFile <int>());

            // Delete sub-directory.

            tx.Transact(nonExistentNestedSubDirectoryPath).DeleteDirectory();

            Assert.IsFalse(nonExistentNestedSubDirectoryPath.IsDirectory());
            Assert.IsFalse(Directory.Exists(nonExistentNestedSubDirectoryPath.FullPath));

            Assert.IsTrue(nonExistentNestedSubDirectoryPath.Parent().IsDirectory());
            Assert.IsTrue(Directory.Exists(nonExistentNestedSubDirectoryPath.Parent().FullPath));

            // Flag file as created.

            File.WriteAllText(jsonFilePath.FullPath, "Hello world!");

            tx.Transact(jsonFilePath).FlagFileCreated();

            // Create directory from ZIP file.

            var zipFilePath = "testing.zip".AsFileSystemPath();

            var testingPath = this.path.Child("testing");

            tx.Transact(testingPath).CreateDirectoryFromZipFile(zipFilePath);

            Assert.IsTrue(testingPath.IsDirectory());
            Assert.IsTrue(Directory.Exists(testingPath.FullPath));

            Assert.AreEqual("Hello World", testingPath.Child("testing.txt").ReadAllText());

            var files = testingPath.GetFiles();

            Assert.AreEqual(1, files.Length);
            Assert.AreEqual("testing.txt", files[0].GetFileName());
            Assert.AreEqual("testing", files[0].GetFileNameWithoutExtension());
            Assert.AreEqual(".txt", files[0].GetExtension());

            // Delete file.

            tx.Transact(jsonFilePath).DeleteFile();

            Assert.IsFalse(jsonFilePath.IsFile());
            Assert.IsFalse(File.Exists(jsonFilePath.FullPath));

            // Attempt to read non-existent file.

            var exceptions = 0;

            try
            {
                jsonFilePath.ReadAllText();
            }
            catch (FileNotFoundException)
            {
                exceptions++;
            }

            Assert.AreEqual(1, exceptions);

            // Get files from non-existent directory.

            try
            {
                nonExistentNestedSubDirectoryPath.GetFiles();
            }
            catch (DirectoryNotFoundException)
            {
                exceptions++;
            }

            Assert.AreEqual(2, exceptions);
        }