Win32 API トランザクションNTFSを使って、ファイル操作をアトミックにする CreateTransaction
Windows Vistaから搭載されたTransactional NTFSという機能で、ファイル操作に対してトランザクション処理を行えるようになりました。
例えば、[ファイル1 作成]→[ディレクトリ1 作成]→[ファイル2 作成] という複数のファイルシステム上の操作をアトミックに行うことができます。途中に失敗などでコミットすることなくトランザクションを終了した場合(または、明示的にロールバックした場合)、この一連の処理はロールバックされるということになります。
実際のAPI呼び出しの流れは、おおよそ以下のようになります。
No | 処理内容 |
---|---|
1 | CreateTransactionでトランザクションハンドルを取得し、トランザクション開始 |
2 | トランザクションハンドルを使用して、各種ファイル操作を行う |
3 | CommitTransactionでトランザクションをコミット |
4 | CloseTransactionでトランザクション終了 |
また、ファイル操作に対してトランザクションを適用する際には、従来のファイル操作APIの名前に「Transacted」が付いた、「XxxxTransacted」という名前のファイル操作APIを使用します。
例えば、以下のようなAPIがあります。
CreateFileTransacted | CreateDirectoryTransacted |
FindFirstFileTransacted | DeleteFileTransacted |
CopyFileTransacted | GetLongPathNameTransacted |
MoveFileTransacted | CreateSymbolicLinkTransacted |
CreateHardLinkTransacted | GetFileAttributesTransacted |
FindFirstFileNameTransactedW | GetFullPathNameTransacted |
FindFirstStreamTransactedW | GetCompressedFileSizeTransact |
SetFileAttributesTransacted |
CreateTransactionのプロトタイプ
HANDLE WINAPI CreateTransaction( _In_opt_ LPSECURITY_ATTRIBUTES lpTransactionAttributes, _In_opt_ LPGUID UOW, _In_opt_ DWORD CreateOptions, _In_opt_ DWORD IsolationLevel, _In_opt_ DWORD IsolationFlags, _In_opt_ DWORD Timeout, _In_opt_ LPWSTR Description );
引数 | 説明 |
---|---|
lpTransactionAttributes | セキュリティ記述子 |
UOW | 予約済み。0を指定する |
CreateOptions | トランザクション命令のオプション。TRANSACTION_DO_NOT_PROMOTEを指定すると、トランザクションは分散できなくなる。 |
IsolationLevel | 予約済み。0を指定する |
IsolationFlags | 予約済み。0を指定する |
Timeout | タイムアウト期限(ミリ秒で指定する)。0かINFINITEを指定すると、無期限タイムアウト |
Description | ユーザー可読なトランザクションの説明 |
戻り値 |
---|
成功したらトランザクションハンドルを返す。失敗したらINVALID_HANDLE_VALUEを返し、拡張エラー情報を得るには、GetLastErrorを呼び出す。 |
ファイル作成とディレクトリ作成をアトミックに行う
#include <windows.h> #include <KtmW32.h> #pragma comment(lib, "KtmW32.lib") int main() { HANDLE hTran; HANDLE hFile; DWORD dwWrittenBytes; char *lpString = "あいうえお"; TCHAR szFileName[] = TEXT("testfile"); TCHAR szDirName[] = TEXT("testdir"); //トランザクション開始 hTran = CreateTransaction(NULL, 0, TRANSACTION_DO_NOT_PROMOTE, 0, 0, INFINITE, L"あいうえお"); if (hTran == INVALID_HANDLE_VALUE) { return 1; } //ファイル作成 hFile = CreateFileTransacted( szFileName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL, hTran, NULL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return 1; } WriteFile(hFile, lpString, strlen(lpString), &dwWrittenBytes, NULL); //ディレクトリ作成 CreateDirectoryTransacted(NULL, szDirName, NULL, hTran); //トランザクションをコミット CommitTransaction(hTran); //トランザクション終了 CloseHandle(hTran); return 0; }
参考
http://msdn.microsoft.com/ja-jp/library/windows/desktop/aa366011(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363859(v=vs.85).aspx
http://msdn.microsoft.com/ja-jp/library/windows/desktop/aa366001(v=vs.85).aspx
http://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3NTFS