updated file_win and file_pool error handling
This commit is contained in:
parent
480b63b516
commit
9f44c577d7
|
@ -109,7 +109,7 @@ namespace libtorrent
|
||||||
file(fs::path const& p, open_mode m);
|
file(fs::path const& p, open_mode m);
|
||||||
~file();
|
~file();
|
||||||
|
|
||||||
void open(fs::path const& p, open_mode m);
|
bool open(fs::path const& p, open_mode m);
|
||||||
void close();
|
void close();
|
||||||
bool set_size(size_type size);
|
bool set_size(size_type size);
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,8 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
file_pool(int size = 40): m_size(size) {}
|
file_pool(int size = 40): m_size(size) {}
|
||||||
|
|
||||||
boost::shared_ptr<file> open_file(void* st, fs::path const& p, file::open_mode m);
|
boost::shared_ptr<file> open_file(void* st, fs::path const& p
|
||||||
|
, file::open_mode m, std::string& error);
|
||||||
void release(void* st);
|
void release(void* st);
|
||||||
void resize(int size);
|
void resize(int size);
|
||||||
|
|
||||||
|
@ -74,9 +75,7 @@ namespace libtorrent
|
||||||
|
|
||||||
struct lru_file_entry
|
struct lru_file_entry
|
||||||
{
|
{
|
||||||
lru_file_entry(boost::shared_ptr<file> const& f)
|
lru_file_entry(): last_use(time_now()) {}
|
||||||
: file_ptr(f)
|
|
||||||
, last_use(time_now()) {}
|
|
||||||
mutable boost::shared_ptr<file> file_ptr;
|
mutable boost::shared_ptr<file> file_ptr;
|
||||||
fs::path file_path;
|
fs::path file_path;
|
||||||
void* key;
|
void* key;
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace libtorrent
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(fs::path const& path, int mode)
|
bool open(fs::path const& path, int mode)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(path.is_complete());
|
TORRENT_ASSERT(path.is_complete());
|
||||||
close();
|
close();
|
||||||
|
@ -189,8 +189,10 @@ namespace libtorrent
|
||||||
<< std::strerror(errno);
|
<< std::strerror(errno);
|
||||||
if (!m_error) m_error.reset(new std::string);
|
if (!m_error) m_error.reset(new std::string);
|
||||||
*m_error = msg.str();
|
*m_error = msg.str();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
m_open_mode = mode;
|
m_open_mode = mode;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
|
@ -330,9 +332,9 @@ namespace libtorrent
|
||||||
|
|
||||||
file::~file() {}
|
file::~file() {}
|
||||||
|
|
||||||
void file::open(fs::path const& p, file::open_mode m)
|
bool file::open(fs::path const& p, file::open_mode m)
|
||||||
{
|
{
|
||||||
m_impl->open(p, m.m_mask);
|
return m_impl->open(p, m.m_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::close()
|
void file::close()
|
||||||
|
|
|
@ -41,7 +41,8 @@ namespace libtorrent
|
||||||
using boost::multi_index::nth_index;
|
using boost::multi_index::nth_index;
|
||||||
using boost::multi_index::get;
|
using boost::multi_index::get;
|
||||||
|
|
||||||
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p, file::open_mode m)
|
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
|
||||||
|
, file::open_mode m, std::string& error)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(st != 0);
|
TORRENT_ASSERT(st != 0);
|
||||||
TORRENT_ASSERT(p.is_complete());
|
TORRENT_ASSERT(p.is_complete());
|
||||||
|
@ -57,14 +58,11 @@ namespace libtorrent
|
||||||
|
|
||||||
if (e.key != st)
|
if (e.key != st)
|
||||||
{
|
{
|
||||||
#ifdef BOOST_NO_EXCEPTIONS
|
|
||||||
return boost::shared_ptr<file>();
|
|
||||||
#else
|
|
||||||
// this means that another instance of the storage
|
// this means that another instance of the storage
|
||||||
// is using the exact same file.
|
// is using the exact same file.
|
||||||
throw file_error("torrent uses the same file as another torrent "
|
error = "torrent uses the same file as another torrent "
|
||||||
"(" + p.string() + ")");
|
"(" + p.string() + ")";
|
||||||
#endif
|
return boost::shared_ptr<file>();
|
||||||
}
|
}
|
||||||
|
|
||||||
e.key = st;
|
e.key = st;
|
||||||
|
@ -74,8 +72,13 @@ namespace libtorrent
|
||||||
// the new read/write privilages
|
// the new read/write privilages
|
||||||
i->file_ptr.reset();
|
i->file_ptr.reset();
|
||||||
TORRENT_ASSERT(e.file_ptr.unique());
|
TORRENT_ASSERT(e.file_ptr.unique());
|
||||||
e.file_ptr.reset();
|
e.file_ptr->close();
|
||||||
e.file_ptr.reset(new file(p, m));
|
if (!e.file_ptr->open(p, m))
|
||||||
|
{
|
||||||
|
error = e.file_ptr->error();
|
||||||
|
m_files.erase(i);
|
||||||
|
return boost::shared_ptr<file>();
|
||||||
|
}
|
||||||
e.mode = m;
|
e.mode = m;
|
||||||
}
|
}
|
||||||
pt.replace(i, e);
|
pt.replace(i, e);
|
||||||
|
@ -93,7 +96,18 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
||||||
lt.erase(i);
|
lt.erase(i);
|
||||||
}
|
}
|
||||||
lru_file_entry e(boost::shared_ptr<file>(new file(p, m)));
|
lru_file_entry e;
|
||||||
|
e.file_ptr.reset(new file);
|
||||||
|
if (!e.file_ptr)
|
||||||
|
{
|
||||||
|
error = "no memory";
|
||||||
|
return e.file_ptr;
|
||||||
|
}
|
||||||
|
if (!e.file_ptr->open(p, m))
|
||||||
|
{
|
||||||
|
error = e.file_ptr->error();
|
||||||
|
return boost::shared_ptr<file>();
|
||||||
|
}
|
||||||
e.mode = m;
|
e.mode = m;
|
||||||
e.key = st;
|
e.key = st;
|
||||||
e.file_path = p;
|
e.file_path = p;
|
||||||
|
|
110
src/file_win.cpp
110
src/file_win.cpp
|
@ -81,36 +81,7 @@ namespace
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void throw_exception(const char* thrower)
|
|
||||||
{
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
wchar_t *wbuffer = 0;
|
|
||||||
FormatMessage(
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM
|
|
||||||
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|
|
||||||
, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
|
|
||||||
auto_localfree auto_free(wbuffer);
|
|
||||||
std::string tmp_utf8;
|
|
||||||
libtorrent::wchar_utf8(wbuffer, tmp_utf8);
|
|
||||||
char const* buffer = tmp_utf8.c_str();
|
|
||||||
#else
|
|
||||||
char* buffer = 0;
|
|
||||||
FormatMessage(
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM
|
|
||||||
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|
|
||||||
, 0, err, 0, (LPSTR)&buffer, 0, 0);
|
|
||||||
auto_localfree auto_free(buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::stringstream s;
|
|
||||||
s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");
|
|
||||||
|
|
||||||
throw libtorrent::file_error(s.str());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -130,12 +101,42 @@ namespace libtorrent
|
||||||
seek_end = FILE_END
|
seek_end = FILE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void set_error(const char* thrower)
|
||||||
|
{
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
wchar_t *wbuffer = 0;
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM
|
||||||
|
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||||
|
, 0, err, 0, (LPWSTR)&wbuffer, 0, 0);
|
||||||
|
auto_localfree auto_free(wbuffer);
|
||||||
|
std::string tmp_utf8;
|
||||||
|
libtorrent::wchar_utf8(wbuffer, tmp_utf8);
|
||||||
|
char const* buffer = tmp_utf8.c_str();
|
||||||
|
#else
|
||||||
|
char* buffer = 0;
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM
|
||||||
|
|FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||||
|
, 0, err, 0, (LPSTR)&buffer, 0, 0);
|
||||||
|
auto_localfree auto_free(buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL");
|
||||||
|
|
||||||
|
if (!m_error) m_error.reset(new std::string);
|
||||||
|
*m_error = s.str();
|
||||||
|
}
|
||||||
|
|
||||||
impl()
|
impl()
|
||||||
{
|
{
|
||||||
m_file_handle = INVALID_HANDLE_VALUE;
|
m_file_handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void open(const char *file_name, open_flags flags)
|
bool open(const char *file_name, open_flags flags)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(file_name);
|
TORRENT_ASSERT(file_name);
|
||||||
TORRENT_ASSERT(flags & (read_flag | write_flag));
|
TORRENT_ASSERT(flags & (read_flag | write_flag));
|
||||||
|
@ -170,7 +171,10 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (new_handle == INVALID_HANDLE_VALUE)
|
if (new_handle == INVALID_HANDLE_VALUE)
|
||||||
throw_exception(file_name);
|
{
|
||||||
|
set_error(file_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// try to make the file sparse if supported
|
// try to make the file sparse if supported
|
||||||
if (access_mask & GENERIC_WRITE)
|
if (access_mask & GENERIC_WRITE)
|
||||||
{
|
{
|
||||||
|
@ -181,6 +185,7 @@ namespace libtorrent
|
||||||
// will only close old file if the open succeeded
|
// will only close old file if the open succeeded
|
||||||
close();
|
close();
|
||||||
m_file_handle = new_handle;
|
m_file_handle = new_handle;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close()
|
void close()
|
||||||
|
@ -211,7 +216,8 @@ namespace libtorrent
|
||||||
, &bytes_written
|
, &bytes_written
|
||||||
, 0))
|
, 0))
|
||||||
{
|
{
|
||||||
throw_exception("file::write");
|
set_error("file::write");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
|
@ -233,20 +239,23 @@ namespace libtorrent
|
||||||
, &bytes_read
|
, &bytes_read
|
||||||
, 0))
|
, 0))
|
||||||
{
|
{
|
||||||
throw_exception("file::read");
|
set_error("file::set_size");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_size(size_type s)
|
bool set_size(size_type s)
|
||||||
{
|
{
|
||||||
size_type pos = tell();
|
size_type pos = tell();
|
||||||
seek(s, seek_begin);
|
seek(s, seek_begin);
|
||||||
if (FALSE == ::SetEndOfFile(m_file_handle))
|
if (FALSE == ::SetEndOfFile(m_file_handle))
|
||||||
throw_exception("file::set_size");
|
{
|
||||||
|
set_error("file::set_size");
|
||||||
seek(pos, seek_begin);
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type seek(size_type pos, seek_mode from_where)
|
size_type seek(size_type pos, seek_mode from_where)
|
||||||
|
@ -261,7 +270,8 @@ namespace libtorrent
|
||||||
, &offs
|
, &offs
|
||||||
, from_where))
|
, from_where))
|
||||||
{
|
{
|
||||||
throw_exception("file::seek");
|
set_error("file::seek");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return offs.QuadPart;
|
return offs.QuadPart;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +288,8 @@ namespace libtorrent
|
||||||
, &offs
|
, &offs
|
||||||
, FILE_CURRENT))
|
, FILE_CURRENT))
|
||||||
{
|
{
|
||||||
throw_exception("file::tell");
|
set_error("file::tell");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type pos = offs.QuadPart;
|
size_type pos = offs.QuadPart;
|
||||||
|
@ -299,9 +310,17 @@ namespace libtorrent
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
std::string const& error() const
|
||||||
|
{
|
||||||
|
if (!m_error) m_error.reset(new std::string);
|
||||||
|
return *m_error;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
HANDLE m_file_handle;
|
HANDLE m_file_handle;
|
||||||
|
mutable boost::scoped_ptr<std::string> m_error;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -329,10 +348,10 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::open(boost::filesystem::path const& p, open_mode m)
|
bool file::open(boost::filesystem::path const& p, open_mode m)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(p.is_complete());
|
TORRENT_ASSERT(p.is_complete());
|
||||||
m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
|
return m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::close()
|
void file::close()
|
||||||
|
@ -350,9 +369,9 @@ namespace libtorrent
|
||||||
return m_impl->read(buffer, num_bytes);
|
return m_impl->read(buffer, num_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::set_size(size_type s)
|
bool file::set_size(size_type s)
|
||||||
{
|
{
|
||||||
m_impl->set_size(s);
|
return m_impl->set_size(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type file::seek(size_type pos, seek_mode m)
|
size_type file::seek(size_type pos, seek_mode m)
|
||||||
|
@ -364,4 +383,9 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
return m_impl->tell();
|
return m_impl->tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string const& file::error() const
|
||||||
|
{
|
||||||
|
return m_impl->error();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,8 +472,10 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
if (allocate_files)
|
if (allocate_files)
|
||||||
{
|
{
|
||||||
|
std::string error;
|
||||||
boost::shared_ptr<file> f = m_files.open_file(this
|
boost::shared_ptr<file> f = m_files.open_file(this
|
||||||
, m_save_path / file_iter->path, file::in | file::out);
|
, m_save_path / file_iter->path, file::in | file::out
|
||||||
|
, error);
|
||||||
if (f && f->error().empty())
|
if (f && f->error().empty())
|
||||||
f->set_size(file_iter->size);
|
f->set_size(file_iter->size);
|
||||||
}
|
}
|
||||||
|
@ -829,21 +831,20 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int buf_pos = 0;
|
int buf_pos = 0;
|
||||||
|
std::string error;
|
||||||
boost::shared_ptr<file> in(m_files.open_file(
|
boost::shared_ptr<file> in(m_files.open_file(
|
||||||
this, m_save_path / file_iter->path, file::in));
|
this, m_save_path / file_iter->path, file::in
|
||||||
|
, error));
|
||||||
if (!in)
|
if (!in)
|
||||||
{
|
{
|
||||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
m_error = "failed to open file ";
|
||||||
|
m_error += (m_save_path / file_iter->path).string();
|
||||||
|
m_error += ": ";
|
||||||
|
m_error += error;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!in->error().empty())
|
TORRENT_ASSERT(in->error().empty());
|
||||||
{
|
|
||||||
m_error = in->error();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||||
|
|
||||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||||
|
|
||||||
size_type new_pos = in->seek(file_offset + file_iter->file_base);
|
size_type new_pos = in->seek(file_offset + file_iter->file_base);
|
||||||
|
@ -927,18 +928,18 @@ namespace libtorrent
|
||||||
fs::path path = m_save_path / file_iter->path;
|
fs::path path = m_save_path / file_iter->path;
|
||||||
|
|
||||||
file_offset = 0;
|
file_offset = 0;
|
||||||
|
std::string error;
|
||||||
in = m_files.open_file(
|
in = m_files.open_file(
|
||||||
this, path, file::in);
|
this, path, file::in, error);
|
||||||
if (!in)
|
if (!in)
|
||||||
{
|
{
|
||||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
m_error = "failed to open file ";
|
||||||
return -1;
|
m_error += path.string();
|
||||||
}
|
m_error += ": ";
|
||||||
if (!in->error().empty())
|
m_error += error;
|
||||||
{
|
|
||||||
m_error = in->error();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
TORRENT_ASSERT(in->error().empty());
|
||||||
in->seek(file_iter->file_base);
|
in->seek(file_iter->file_base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,19 +982,19 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path p(m_save_path / file_iter->path);
|
fs::path p(m_save_path / file_iter->path);
|
||||||
|
std::string error;
|
||||||
boost::shared_ptr<file> out = m_files.open_file(
|
boost::shared_ptr<file> out = m_files.open_file(
|
||||||
this, p, file::out | file::in);
|
this, p, file::out | file::in, error);
|
||||||
|
|
||||||
if (!out)
|
if (!out)
|
||||||
{
|
{
|
||||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
m_error = "failed to open file ";
|
||||||
|
m_error += p.string();
|
||||||
|
m_error += ": ";
|
||||||
|
m_error += error;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!out->error().empty())
|
TORRENT_ASSERT(out->error().empty());
|
||||||
{
|
|
||||||
m_error = out->error();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||||
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
|
||||||
|
|
||||||
|
@ -1060,18 +1061,19 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(file_iter != m_info->end_files(true));
|
TORRENT_ASSERT(file_iter != m_info->end_files(true));
|
||||||
fs::path p = m_save_path / file_iter->path;
|
fs::path p = m_save_path / file_iter->path;
|
||||||
file_offset = 0;
|
file_offset = 0;
|
||||||
|
std::string error;
|
||||||
out = m_files.open_file(
|
out = m_files.open_file(
|
||||||
this, p, file::out | file::in);
|
this, p, file::out | file::in, error);
|
||||||
|
|
||||||
if (!out)
|
if (!out)
|
||||||
{
|
{
|
||||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
m_error = "failed to open file ";
|
||||||
return -1;
|
m_error += p.string();
|
||||||
}
|
m_error += ": ";
|
||||||
if (!out->error().empty())
|
m_error += error;
|
||||||
{
|
|
||||||
m_error = out->error();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
TORRENT_ASSERT(out->error().empty());
|
||||||
|
|
||||||
out->seek(file_iter->file_base);
|
out->seek(file_iter->file_base);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue