support locking files

This commit is contained in:
Arvid Norberg 2011-06-09 06:08:24 +00:00
parent 67ad61fd0a
commit d6c8184381
6 changed files with 61 additions and 23 deletions

View File

@ -4393,7 +4393,8 @@ struct session_settings
bool always_send_user_agent;
bool apply_ip_filter_to_trackers;
int read_job_every;
use_disk_read_ahead;
bool use_disk_read_ahead;
bool lock_files;
};
</pre>
<p><tt class="docutils literal"><span class="pre">version</span></tt> is automatically set to the libtorrent version you're using
@ -5115,6 +5116,10 @@ instead pick one read job off of the sorted queue, where <em>x</em> is <tt class
<p><tt class="docutils literal"><span class="pre">use_disk_read_ahead</span></tt> defaults to true and will attempt to optimize disk reads
by giving the operating system heads up of disk read requests as they are queued
in the disk job queue. This gives a significant performance boost for seeding.</p>
<p><tt class="docutils literal"><span class="pre">lock_files</span></tt> determines whether or not to lock files which libtorrent is downloading
to or seeding from. This is implemented using <tt class="docutils literal"><span class="pre">fcntl(F_SETLK)</span></tt> on unix systems and
by not passing in <tt class="docutils literal"><span class="pre">SHARE_READ</span></tt> and <tt class="docutils literal"><span class="pre">SHARE_WRITE</span></tt> on windows. This might prevent
3rd party processes from corrupting the files under libtorrent's feet.</p>
</div>
</div>
<div class="section" id="pe-settings">

View File

@ -4405,7 +4405,8 @@ session_settings
bool always_send_user_agent;
bool apply_ip_filter_to_trackers;
int read_job_every;
use_disk_read_ahead;
bool use_disk_read_ahead;
bool lock_files;
};
``version`` is automatically set to the libtorrent version you're using
@ -5274,6 +5275,11 @@ instead pick one read job off of the sorted queue, where *x* is ``read_job_every
by giving the operating system heads up of disk read requests as they are queued
in the disk job queue. This gives a significant performance boost for seeding.
``lock_files`` determines whether or not to lock files which libtorrent is downloading
to or seeding from. This is implemented using ``fcntl(F_SETLK)`` on unix systems and
by not passing in ``SHARE_READ`` and ``SHARE_WRITE`` on windows. This might prevent
3rd party processes from corrupting the files under libtorrent's feet.
pe_settings
===========

View File

@ -182,10 +182,10 @@ namespace libtorrent
read_write = 2,
rw_mask = read_only | write_only | read_write,
no_buffer = 4,
mode_mask = rw_mask | no_buffer,
sparse = 8,
no_atime = 16,
random_access = 32,
lock_file = 64,
attribute_hidden = 0x1000,
attribute_executable = 0x2000,

View File

@ -269,6 +269,7 @@ namespace libtorrent
, apply_ip_filter_to_trackers(true)
, read_job_every(10)
, use_disk_read_ahead(true)
, lock_files(false)
{}
// libtorrent version. Used for forward binary compatibility
@ -1075,6 +1076,10 @@ namespace libtorrent
// issue posix_fadvise() or fcntl(F_RDADVISE) for disk reads
// ahead of time
bool use_disk_read_ahead;
// if set to true, files will be locked when opened.
// preventing any other process from modifying them
bool lock_files;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -755,29 +755,17 @@ namespace libtorrent
struct open_mode_t
{
DWORD rw_mode;
DWORD share_mode;
DWORD create_mode;
DWORD flags;
};
const static open_mode_t mode_array[] =
{
// read_only
{GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, 0},
{GENERIC_READ, OPEN_EXISTING},
// write_only
{GENERIC_WRITE, FILE_SHARE_READ, OPEN_ALWAYS, 0},
{GENERIC_WRITE, OPEN_ALWAYS},
// read_write
{GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, 0},
// invalid option
{0,0,0,0},
// read_only no_buffer
{GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING },
// write_only no_buffer
{GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING },
// read_write no_buffer
{GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING },
// invalid option
{0,0,0,0}
{GENERIC_WRITE | GENERIC_READ, OPEN_ALWAYS},
};
const static DWORD attrib_array[] =
@ -788,6 +776,16 @@ namespace libtorrent
FILE_ATTRIBUTE_HIDDEN, // hidden + executable
};
const static DWORD share_array[] =
{
// read only (no locking)
FILE_SHARE_READ | FILE_SHARE_WRITE,
// write only (no locking)
FILE_SHARE_READ,
// read/write (no locking)
FILE_SHARE_READ,
};
#if TORRENT_USE_WSTRING
#define CreateFile_ CreateFileW
m_path = convert_to_wstring(path);
@ -797,14 +795,17 @@ namespace libtorrent
#endif
TORRENT_ASSERT((mode & mode_mask) < sizeof(mode_array)/sizeof(mode_array[0]));
open_mode_t const& m = mode_array[mode & mode_mask];
open_mode_t const& m = mode_array[mode & rw_mask];
DWORD a = attrib_array[(mode & attribute_mask) >> 12];
DWORD extra_flags = ((mode & random_access) ? FILE_FLAG_RANDOM_ACCESS : 0)
| (a ? a : FILE_ATTRIBUTE_NORMAL);
DWORD flags
= ((mode & random_access) ? FILE_FLAG_RANDOM_ACCESS : 0)
| (a ? a : FILE_ATTRIBUTE_NORMAL)
| ((mode & no_buffer) ? FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING : 0);
m_file_handle = CreateFile_(m_path.c_str(), m.rw_mode, m.share_mode, 0
, m.create_mode, m.flags | extra_flags, 0);
m_file_handle = CreateFile_(m_path.c_str(), m.rw_mode
, (mode & lock_file) ? 0 : share_array[mode & rw_mask]
, 0, m.create_mode, flags, 0);
if (m_file_handle == INVALID_HANDLE_VALUE)
{
@ -869,6 +870,25 @@ namespace libtorrent
return false;
}
#ifdef F_SETLK
if (mode & lock_file)
{
struct flock l =
{
0, // start offset
0, // length (0 = until EOF)
getpid(), // owner
(mode & write_only) ? F_WRLCK : F_RDLCK, // lock type
SEEK_SET // whence
};
if (fcntl(m_fd, F_SETLK, &l) != 0)
{
ec.assign(errno, get_posix_category());
return false;
}
}
#endif
#ifdef DIRECTIO_ON
// for solaris
if (mode & no_buffer)

View File

@ -1382,6 +1382,8 @@ ret:
|| (cache_setting == session_settings::disable_os_cache_for_aligned_files
&& ((fe->offset + files().file_base(*fe)) & (m_page_size-1)) == 0))
mode |= file::no_buffer;
bool lock_files = m_settings ? settings().lock_files : false;
if (lock_files) mode |= file::lock_file;
if (!m_allocate_files) mode |= file::sparse;
if (m_settings && settings().no_atime_storage) mode |= file::no_atime;