improve support for windows XP and earlier

This commit is contained in:
Arvid Norberg 2013-01-07 01:56:40 +00:00
parent 640f3e1f2d
commit 3788ed23ca
3 changed files with 115 additions and 24 deletions

View File

@ -1,3 +1,4 @@
* improve support for windows XP and earlier
* introduce global connection priority for improved swarm performance
* make files deleted alert non-discardable
* make built-in sha functions not conflict with libcrypto

View File

@ -1813,25 +1813,53 @@ namespace libtorrent
return false;
}
}
#if _WIN32_WINNT >= 0x501
if ((m_open_mode & sparse) == 0)
{
// only allocate the space if the file
// is not fully allocated
DWORD high_dword = 0;
offs.LowPart = GetCompressedFileSize(m_path.c_str(), &high_dword);
offs.HighPart = high_dword;
ec.assign(GetLastError(), get_system_category());
if (ec) return false;
if (offs.QuadPart != s)
typedef DWORD (WINAPI *GetCompressedFileSizeW_t)(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh);
typedef BOOL (WINAPI *SetFileValidData_t)(HANDLE hFile, LONGLONG ValidDataLength);
static GetCompressedFileSizeW_t GetCompressedFileSizeW = NULL;
static SetFileValidData_t SetFileValidData = NULL;
static bool failed_kernel32 = false;
if ((GetCompressedFileSizeW == NULL) && !failed_kernel32)
{
// if the user has permissions, avoid filling
// the file with zeroes, but just fill it with
// garbage instead
SetFileValidData(m_file_handle, offs.QuadPart);
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
if (kernel32)
{
GetCompressedFileSizeW = (GetCompressedFileSizeW_t)GetProcAddress(kernel32, "GetCompressedFileSizeW");
SetFileValidData = (SetFileValidData_t)GetProcAddress(kernel32, "SetFileValidData");
if ((GetCompressedFileSizeW == NULL) || (SetFileValidData == NULL))
{
failed_kernel32 = true;
}
}
else
{
failed_kernel32 = true;
}
}
if (!failed_kernel32 && GetCompressedFileSizeW && SetFileValidData)
{
// only allocate the space if the file
// is not fully allocated
DWORD high_dword = 0;
offs.LowPart = GetCompressedFileSize(m_path.c_str(), &high_dword);
offs.HighPart = high_dword;
ec.assign(GetLastError(), get_system_category());
if (ec) return false;
if (offs.QuadPart != s)
{
// if the user has permissions, avoid filling
// the file with zeroes, but just fill it with
// garbage instead
SetFileValidData(m_file_handle, offs.QuadPart);
}
}
}
#endif // _WIN32_WINNT >= 0x501
#else // NON-WINDOWS
struct stat st;
if (fstat(m_fd, &st) != 0)

View File

@ -101,6 +101,73 @@ namespace libtorrent
}
#endif
#ifdef TORRENT_WINDOWS
void set_low_priority(boost::intrusive_ptr<file> const& f)
{
// file prio is only supported on vista and up
// so load the functions dynamically
typedef enum _FILE_INFO_BY_HANDLE_CLASS {
FileBasicInfo,
FileStandardInfo,
FileNameInfo,
FileRenameInfo,
FileDispositionInfo,
FileAllocationInfo,
FileEndOfFileInfo,
FileStreamInfo,
FileCompressionInfo,
FileAttributeTagInfo,
FileIdBothDirectoryInfo,
FileIdBothDirectoryRestartInfo,
FileIoPriorityHintInfo,
FileRemoteProtocolInfo,
MaximumFileInfoByHandleClass
} FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;
typedef enum _PRIORITY_HINT {
IoPriorityHintVeryLow = 0,
IoPriorityHintLow,
IoPriorityHintNormal,
MaximumIoPriorityHintType
} PRIORITY_HINT;
typedef struct _FILE_IO_PRIORITY_HINT_INFO {
PRIORITY_HINT PriorityHint;
} FILE_IO_PRIORITY_HINT_INFO, *PFILE_IO_PRIORITY_HINT_INFO;
typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
static SetFileInformationByHandle_t SetFileInformationByHandle = NULL;
static bool failed_kernel_load = false;
if (failed_kernel_load) return;
if (SetFileInformationByHandle == NULL)
{
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
if (kernel32 == NULL)
{
failed_kernel_load = true;
return;
}
SetFileInformationByHandle = (SetFileInformationByHandle_t)GetProcAddress(kernel32, "SetFileInformationByHandle");
if (SetFileInformationByHandle == NULL)
{
failed_kernel_load = true;
return;
}
}
TORRENT_ASSERT(SetFileInformationByHandle);
FILE_IO_PRIORITY_HINT_INFO io_hint;
io_hint.PriorityHint = IoPriorityHintLow;
SetFileInformationByHandle(f->native_handle(),
FileIoPriorityHintInfo, &io_hint, sizeof(io_hint));
}
#endif // TORRENT_WINDOWS
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p
, file_storage::iterator fe, file_storage const& fs, int m, error_code& ec)
{
@ -154,17 +221,8 @@ namespace libtorrent
return boost::intrusive_ptr<file>();
}
#ifdef TORRENT_WINDOWS
// file prio is supported on vista and up
#if _WIN32_WINNT >= 0x0600
if (m_low_prio_io)
{
// TODO: load this function dynamically from Kernel32.dll
FILE_IO_PRIORITY_HINT_INFO priorityHint;
priorityHint.PriorityHint = IoPriorityHintLow;
SetFileInformationByHandle(e.file_ptr->native_handle(),
FileIoPriorityHintInfo, &priorityHint, sizeof(priorityHint));
}
#endif
set_low_priority(e.file_ptr);
#endif
TORRENT_ASSERT(e.file_ptr->is_open());
e.mode = m;
@ -189,6 +247,10 @@ namespace libtorrent
std::string full_path = combine_path(p, fs.file_path(*fe));
if (!e.file_ptr->open(full_path, m, ec))
return boost::intrusive_ptr<file>();
#ifdef TORRENT_WINDOWS
if (m_low_prio_io)
set_low_priority(e.file_ptr);
#endif
e.mode = m;
e.key = st;
m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(*fe)), e));