Sunday, November 05, 2006 5:29 AM bart

Windows Vista - Introducing TxF in C# (part 1) - Transacted file delete

Introduction

TxF is another great Vista technology that allows you to manipulate files and the registry in a transacted way, in concert with other transactional operations on the system or the network. Imagine a business process that has to update a database, create a file, call a webservice, etc all in a transacted manner. With TxF this kind of thing becomes possible. To my own surprise, I didn't blog about TxF yet from a more technical point of view. However in this post, I'll do :-). We'll start rather simple with a transacted file delete, and in future posts we'll dive deeper and deeper, each time making things easier for managed code developers too (although the real summum of TxF in managed code would be a core change to the BCL). The goal of this first post is to show some key players and basic approaches in the TxF world.

Your new friends are *Transacted

Since the early Vista days, things have changed quite a bit. The first approach the dev teams took, was to keep the Win32 API functions for file I/O intact, e.g. CreateFile or DeleteFile. Only the internals changed, so that if a Kernel Transaction Manager (KTM) transaction is in flight, that transaction would be used (to put things easy and set the mind in this post). However, another approach was taken to bring transactions to file I/O, namely the use of the Transacted suffix, like CreateFileTransacted and DeleteFileTransacted, amongst others (see later posts). Since the latter function has the simplest signature, it seemed an attractive candidate for TxF introduction to me. Here it is:

BOOL WINAPI DeleteFileTransacted( LPCTSTR lpFileName, HANDLE hTransaction );

Where the non-transacted function only had one parameter, this function carries a handle to the KTM transaction to enroll in.

The KTM in a few words

On to the KTM stuff right now. As mentioned earlier, KTM stands for Kernel Transaction Manager. Don't get confused by the word kernel, it only refers to the fact the KTM's transaction engine is in the kernel. This doesn't imply the transaction can only run in kernel mode (i.e. KTM-transactions can be used in kernel and user mode) nor does it mean the transaction would be machine-local (i.e. the transaction is DTC-able). On Vista and Longhorn Server, the KTM is in charge of TxF (Transactional NTFS) and TxR (Transactional Registry).

Important remark: Today we walk the low-level path, interacting directly with the KTM. This is not the ideal way but just a mind-setter for follow-up posts. Later on, we'll bring System.Transactions on stage to interact with the KTM transaction.

A demo

Transactions are about ACID: atomicity, consistency, isolation and durability. In this first demo, you'll see the atomic character of deleting two files in a transaction, the isolation while the transaction is running, durability once the transaction is committed. Here's the code:

1 using System; 2 using System.Runtime.InteropServices; 3 using System.IO; 4 5 namespace TxF 6 { 7 class Program 8 { 9 [DllImport("Kernel32.dll")] 10 static extern bool DeleteFileTransactedW([MarshalAs(UnmanagedType.LPWStr)]string file, IntPtr transaction); 11 12 [DllImport("Kernel32.dll")] 13 static extern bool CloseHandle(IntPtr handle); 14 15 [DllImport("Ktmw32.dll")] 16 static extern bool CommitTransaction(IntPtr transaction); 17 18 [DllImport("Ktmw32.dll")] 19 static extern bool RollbackTransaction(IntPtr transaction); 20 21 [DllImport("Ktmw32.dll")] 22 static extern IntPtr CreateTransaction(IntPtr securityAttributes, IntPtr guid, int options, int isolationLevel, int isolationFlags, int milliSeconds, string description); 23 24 static void Main(string[] args) 25 { 26 // 27 // Demo setup. 28 // 29 string file1 = "c:\\temp\\txf1.txt"; 30 string file2 = "c:\\temp\\txf2.txt"; 31 using (StreamWriter sw = File.CreateText(file1)) 32 sw.WriteLine("Hello World"); 33 using (StreamWriter sw = File.CreateText(file2)) 34 sw.WriteLine("Hello World"); 35 36 // 37 // Start the demo. 38 // 39 Console.WriteLine("Press <ENTER> to start the transaction."); 40 Console.ReadLine(); 41 42 // 43 // Create a kernel transaction. 44 // 45 IntPtr tx = CreateTransaction(IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, null); 46 47 // 48 // Delete the files (transacted). 49 // 50 bool rollback = false; 51 if (!DeleteFileTransactedW(file1, tx)) 52 rollback = true; 53 if (!DeleteFileTransactedW(file2, tx)) 54 rollback = true; 55 56 // 57 // Commit or rollback? 58 // 59 if (!rollback) 60 { 61 char c; 62 do 63 { 64 Console.WriteLine("{0} {1}.", file1, File.Exists(file1) ? "still exists" : "has vanished"); 65 Console.WriteLine("{0} {1}.", file2, File.Exists(file2) ? "still exists" : "has vanished"); 66 Console.Write("Commit transaction (Y/N)? "); 67 c = (char)Console.Read(); 68 } 69 while (c != 'Y' && c != 'y' && c != 'N' && c != 'n'); 70 71 if (c == 'Y' || c == 'y') 72 CommitTransaction(tx); 73 else 74 RollbackTransaction(tx); 75 } 76 else 77 { 78 Console.WriteLine("Forced rollback!"); 79 RollbackTransaction(tx); 80 } 81 82 // 83 // Close kernel mode transaction handle. 84 // 85 CloseHandle(tx); 86 } 87 } 88 }

It assumes you have a c:\temp folder of course. Two files are created (26-34), called txf1.txt and txf2.txt. Next, the app stops (36-40) to give you a chance to obtain locks to the files from the outside to see what happens in that case. Finally, the real work starts by creating a transaction (45) and performing transacted file deletes (51, 53). Notice we track the success or failure of the transacted operations. In case the file is locked, the transacted delete won't succeed. Next, if no rollback is required, we demand user interaction to decide whether the transaction has to be completed or not (61-69), after which the commit or rollback is done (72, 74). Finally (85) the handle to the KTM transaction is closed.

In action

A simple helper app might be useful to obtain locks from the outside:

using System; using System.IO; class Locker { public static void Main(string[] args) { string f = args[0]; using (File.OpenRead(f)) { Console.WriteLine("{0} locked. Press <ENTER> to unlock.", f); Console.ReadLine(); } } }
Demo 1

1. Start TxF.exe

2. Dir the c:\temp folder, it should contain txf1.txt and txf2.txt

3. Press <ENTER> in TxF.exe to start the transaction and the transacted file deletes.

4. Dir the c:\temp folder, the txf[12].txt files should still be present.

5. In TxF.exe press Y to commit.

6. In c:\temp the txf[12].txt files will be gone.

 

Demo 2

1. Start TxF.exe

2. Dir the c:\temp folder, it should contain txf1.txt and txf2.txt

3. Press <ENTER> in TxF.exe to start the transaction and the transacted file deletes.

4. Dir the c:\temp folder, the txf[12].txt files should still be present.

5. In TxF.exe press N to rollback.

6. In c:\temp the txf[12].txt files will still be there. Remove them via erase txf?.txt

 

Demo 3

1. Start TxF.exe

2. Dir the c:\temp folder, it should contain txf1.txt and txf2.txt

3. Execute locker.exe txf1.txt.

4. Press <ENTER> in TxF.exe to start the transaction and the transacted file deletes.

5. A forced rollback will be executed.

6. Unlock the file by exiting locker.exe.

7. In c:\temp the txf[12].txt files will both be present. Remove them via erase txf?.txt

Demo 4

1. Start TxF.exe

2. Dir the c:\temp folder, it should contain txf1.txt and txf2.txt

3. Press <ENTER> in TxF.exe to start the transaction and the transacted file deletes.

4. Dir the c:\temp folder, the txf[12].txt files should still be present.

5. Try to run locker.exe txf1.txt and notice the file is locked by the transaction in flight.

6. In TxF.exe press Y to commit.

7. In c:\temp the txf[12].txt files will be gone.

 

Conclusion

In this introduction post you learned the basic concepts of the KTM and TxF. Notice that as a managed developer this should be the only time to interact directly with the KTM for demonstration purposes. In a next post, you'll learn how to leverage the power of the KTM, TxF (and TxR) through System.Transactions with little additional plumbing.

Commit!

kick it on DotNetKicks.com

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: , ,

Comments

# Transaction Resources List

Wednesday, November 08, 2006 3:31 PM by Managed World - Jason Olson's Blog

# Managed World - Jason Olson's Blog - Transaction Resources List

Wednesday, November 08, 2006 3:31 PM by Managed World - Jason Olson's Blog - Transaction Resources List

# The November 06 Month Report

Friday, December 01, 2006 4:06 AM by B# .NET Blog

Yet another great (well, at least in my opinion) month of Daily Blogging . Once more, feedback from readers

# Windows Vista - Introducing TxR in C# (Part 1)

Friday, December 22, 2006 3:38 AM by B# .NET Blog

Introduction Last month I blogged about TxF in Windows Vista and how to use it from your own application

# AlphaFS - Bringing Advanced Windows File System support to .NET | Alpha Leonis

Pingback from  AlphaFS - Bringing Advanced Windows File System support to .NET | Alpha Leonis

# rimonabantexcellence site title

Sunday, July 21, 2013 9:01 AM by rimonabantexcellence site title

Pingback from  rimonabantexcellence site title