Hi,
We use the following Win32 API call sequence:
// constructor code
DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH;
If ( useBufferedWrites )
{
flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
}
fileHandle = ::CreateFile(filename.c_str(),
FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
0,
OPEN_ALWAYS,
flagsAndAttributes,
0);
// commitLogEntry() method
DWORD bytesWritten = 0;
::WriteFile( fileHandle, data, (DWORD) numberOfBytesToWrite, &bytesWritten, nullptr );
As you can read from the code, CreateFile will open a file using shared read/write rights and in “append mode”.
The above sequence is part of a logging “output” class which is a singleton
(instantiated once / process) and is used (without any thread/level
synchronization mechanism) for writing log entries from several threads
inside the same process.
So the same log *file* can be simultaneously written from different threads & processes, as our system uses several processes that log to the same file.
It seems that the WriteFile() calls are synchronized internally (at least in this case,
when using FILE_APPEND_DATA and FILE_FLAG_WRITE_THROUGH), so I do not
have to use any other thread/process synchronization mechanism
(semaphore, etc.) at the application level.
As I did not found any Microsoft documentation around this nice feature, I would like to have a
confirmation and better understanding of why this (i.e. thread/process
atomic WriteFile() calls on files opened for append) happens (and of
course I would be grateful for any MSDN / MS reference that I might have
not yet found).
Apart from this, I would kindly ask for some answers on details which I could not grasp from the API pages:
- Our code should be running on Windows 7 and above, as well as on
Windows Server 2008 and above. Is the above mentioned WriteFile()
thread/process atomicity consistent throughout these platforms?
- The log files are stored always on hard-drives (old HDD or the newer
SSDs). Is this atomicity consistent throughout all Windows based
platforms or does it have certain exceptions (like being dependent on
certain file-systems, hard-disk drivers, desktop vs. cluster, etc.)?
- What is the CreateFile() flag that triggers this atomicity? Is it only FILE_APPEND_DATA?
- Our code uses FILE_FLAG_WRITE_THROUGH for making sure that log entries
are committed promptly to disk, so that an (uncontrolled?!) process
crash will contain up-to-date and consistent log information. Of course
this comes with a huge expense (factor 10 on some hw/sw configurations).
On the other side I would imagine that, with or without this flag,
WriteFile() stores its data in a driver buffer which should not be
influenced by any user-space process crash in committing all its pending
data to disk. So the question would be: does FILE_FLAG_WRITE_THROUGH
really help in such crash scenarios for ensuring that everything before a
crash hit the disk or not?
Thank you in advance for you answers.
Kind Regards,
Marius