[Community Ring follow-up 2] Vista (RC1) の TxF をコードで体験する


(更新された情報を こちら に掲載しています  2007/02/23 追記) 


2つ目のデモをアップします。


当日デモは致しませんでしたが、DB との同時トランザクション以外にも、トランザクションを複数作成(もしくは複数のアプリを起動するなどして複数プロセスから処理)した場合も正しく処理されません (この場合は、最初にトランザクションを作成した処理は常に勝ってしまいます)。
ですから、ご説明しました通り、インストール、移動、バックアップ、等々のプリミティブな処理の一貫性を保証するプログラムコードなどの形で活用して頂くと良いと思います。


尚、トランザクション管理用の新しい API については、以下を参照してください。(レジストリ関連は未だないようですが、Longhorn ではおそらく実装されてくるはずです。)


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/file_management_functions.asp


以下、ソースを掲載します。 


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Transactions;
using System.EnterpriseServices;
using System.Windows.Forms;


namespace TxFProject
{
    public class TranHandle
    {
        const ulong WRITE_DAC = (0x00040000L);
        const ulong WRITE_OWNER = (0x00080000L);
        const UInt32 FILE_SHARE_READ = 0x00000001;
        const UInt32 FILE_SHARE_WRITE = 0x00000002;
        const UInt32 FILE_SHARE_DELETE = 0x00000004;
        const UInt32 FILE_ATTRIBUTE_NORMAL = 0x00000080;
        const int CREATE_NEW = 1;
        const int CREATE_ALWAYS = 2;


        public void FireTrans(bool isCommited)
        {
            using (TransactionScope s = new TransactionScope())
            {
                SafeTransactionHandle txHandle;
                IKernelTransaction kernelTx = (IKernelTransaction)TransactionInterop.GetDtcTransaction(Transaction.Current);
                kernelTx.GetHandle(out txHandle);


                // Update Win32 file 1
                SafeFileHandle fileHandle1 = CreateFileTransacted(@"C:\TxF\hello1.txt",
                    (int)WRITE_DAC,
                    (int)(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
                    System.IntPtr.Zero,
                    CREATE_ALWAYS,
                    (int)FILE_ATTRIBUTE_NORMAL,
                    new SafeFileHandle(System.IntPtr.Zero, false),
                    txHandle,
                    System.IntPtr.Zero,
                    System.IntPtr.Zero);


                #region FILE2
                // Update Win32 file 2
                SafeFileHandle fileHandle2 = CreateFileTransacted(@"C:\TxF\hello2.txt",
                    (int)WRITE_DAC,
                    (int)(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
                    System.IntPtr.Zero,
                    CREATE_ALWAYS,
                    (int)FILE_ATTRIBUTE_NORMAL,
                    new SafeFileHandle(System.IntPtr.Zero, false),
                    txHandle,
                    System.IntPtr.Zero,
                    System.IntPtr.Zero);
                #endregion


                #region DB
/*****
ここ↓は、どう頑張っても、同一トランザクションの配下に入れることはできません
(TransactionScope を RequiredNew にすれば無論動きますが、意味がありません、、、)
*****/
                //// Update database
                //SqlConnection conDB = new SqlConnection(@"Data Source=tsmatsuz31\SQLEXPRESS;Integrated Security=SSPI;Initial Catalog=HOL_DB");
                //conDB.Open();
                //SqlCommand cmdSql = new SqlCommand("insert into TestTbl (ID, Name) values (1, 'Test Data')", conDB);
                //cmdSql.ExecuteNonQuery();
                //conDB.Close();
                #endregion


                MessageBox.Show("更新完了");


                if(isCommited)
                    s.Complete();
                else
                    s.Dispose();
            }
        }


        [DllImport("Kernel32.Dll",
               CallingConvention = CallingConvention.StdCall,
               CharSet = CharSet.Unicode)]
        internal static extern SafeFileHandle CreateFileTransacted(
            String lpFileName,
            int dwDesiredAccess,
            int dwShareMode,
            IntPtr lpSecurityAttributes,
            int dwCreationDisposition,
            int dwFlagsAndAttributes,
            SafeFileHandle hTemplateFile,
            SafeTransactionHandle txHandle,
            IntPtr miniVersion,
            IntPtr extendedOpenInformation);


        [ComImport]
        [Guid("79427A2B-F895-40e0-BE79-B57DC82ED231")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IKernelTransaction
        {
            void GetHandle(out SafeTransactionHandle ktmHandle);
        }


    }


    [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    public sealed class SafeTransactionHandle : SafeHandleZeroOrMinusOneIsInvalid
    {


        private SafeTransactionHandle()
            : base(true)
        {
        }


        public SafeTransactionHandle(IntPtr preexistingHandle, bool ownsHandle)
            : base(ownsHandle)
        {
            SetHandle(preexistingHandle);
        }


        [DllImport("Kernel32.dll", SetLastError = true)]
        [ResourceExposure(ResourceScope.Machine)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        private static extern bool CloseHandle(IntPtr handle);


        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        override protected bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }


    }


}


 

CommunityRing_Demo2.zip

Comments (4)

  1. develop .net says:

    11/5(日)には、秋葉原コンベンションホールで「 Microsoft Community Ring Day 」というイベントが開催されました。このイベントは、9月にはじまった新たなコミュニティへの支援活動「

  2. 松崎さんのブログでCommunity Ringのエバンジェリストデモフェスティバルで行われたデモのコードが紹介されています。

  3. こんにちは。舟越です。 11月に開催されたコミュニティの方々に向けたイベント Microsoft Community Ring Day の セッションをストリーミング配信中です。(一部対象外のものもあります)

  4. TxF (Transactional NTFS) を使って RDBMS, MSMQ,,, と相互運用させる (RTM 版でばっちり動作します!(松崎 剛 ブログ)より

Skip to main content