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();
|
||||
|
||||
void open(fs::path const& p, open_mode m);
|
||||
bool open(fs::path const& p, open_mode m);
|
||||
void close();
|
||||
bool set_size(size_type size);
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ namespace libtorrent
|
|||
{
|
||||
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 resize(int size);
|
||||
|
||||
|
@ -74,9 +75,7 @@ namespace libtorrent
|
|||
|
||||
struct lru_file_entry
|
||||
{
|
||||
lru_file_entry(boost::shared_ptr<file> const& f)
|
||||
: file_ptr(f)
|
||||
, last_use(time_now()) {}
|
||||
lru_file_entry(): last_use(time_now()) {}
|
||||
mutable boost::shared_ptr<file> file_ptr;
|
||||
fs::path file_path;
|
||||
void* key;
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace libtorrent
|
|||
close();
|
||||
}
|
||||
|
||||
void open(fs::path const& path, int mode)
|
||||
bool open(fs::path const& path, int mode)
|
||||
{
|
||||
TORRENT_ASSERT(path.is_complete());
|
||||
close();
|
||||
|
@ -189,8 +189,10 @@ namespace libtorrent
|
|||
<< std::strerror(errno);
|
||||
if (!m_error) m_error.reset(new std::string);
|
||||
*m_error = msg.str();
|
||||
return false;
|
||||
}
|
||||
m_open_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
void close()
|
||||
|
@ -330,9 +332,9 @@ namespace libtorrent
|
|||
|
||||
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()
|
||||
|
|
|
@ -41,7 +41,8 @@ namespace libtorrent
|
|||
using boost::multi_index::nth_index;
|
||||
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(p.is_complete());
|
||||
|
@ -57,14 +58,11 @@ namespace libtorrent
|
|||
|
||||
if (e.key != st)
|
||||
{
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return boost::shared_ptr<file>();
|
||||
#else
|
||||
// this means that another instance of the storage
|
||||
// is using the exact same file.
|
||||
throw file_error("torrent uses the same file as another torrent "
|
||||
"(" + p.string() + ")");
|
||||
#endif
|
||||
error = "torrent uses the same file as another torrent "
|
||||
"(" + p.string() + ")";
|
||||
return boost::shared_ptr<file>();
|
||||
}
|
||||
|
||||
e.key = st;
|
||||
|
@ -74,8 +72,13 @@ namespace libtorrent
|
|||
// the new read/write privilages
|
||||
i->file_ptr.reset();
|
||||
TORRENT_ASSERT(e.file_ptr.unique());
|
||||
e.file_ptr.reset();
|
||||
e.file_ptr.reset(new file(p, m));
|
||||
e.file_ptr->close();
|
||||
if (!e.file_ptr->open(p, m))
|
||||
{
|
||||
error = e.file_ptr->error();
|
||||
m_files.erase(i);
|
||||
return boost::shared_ptr<file>();
|
||||
}
|
||||
e.mode = m;
|
||||
}
|
||||
pt.replace(i, e);
|
||||
|
@ -93,7 +96,18 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
||||
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.key = st;
|
||||
e.file_path = p;
|
||||
|
|
110
src/file_win.cpp
110
src/file_win.cpp
|
@ -81,36 +81,7 @@ namespace
|
|||
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
|
||||
{
|
||||
|
@ -130,12 +101,42 @@ namespace libtorrent
|
|||
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()
|
||||
{
|
||||
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(flags & (read_flag | write_flag));
|
||||
|
@ -170,7 +171,10 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
if (new_handle == INVALID_HANDLE_VALUE)
|
||||
throw_exception(file_name);
|
||||
{
|
||||
set_error(file_name);
|
||||
return false;
|
||||
}
|
||||
// try to make the file sparse if supported
|
||||
if (access_mask & GENERIC_WRITE)
|
||||
{
|
||||
|
@ -181,6 +185,7 @@ namespace libtorrent
|
|||
// will only close old file if the open succeeded
|
||||
close();
|
||||
m_file_handle = new_handle;
|
||||
return true;
|
||||
}
|
||||
|
||||
void close()
|
||||
|
@ -211,7 +216,8 @@ namespace libtorrent
|
|||
, &bytes_written
|
||||
, 0))
|
||||
{
|
||||
throw_exception("file::write");
|
||||
set_error("file::write");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return bytes_written;
|
||||
|
@ -233,20 +239,23 @@ namespace libtorrent
|
|||
, &bytes_read
|
||||
, 0))
|
||||
{
|
||||
throw_exception("file::read");
|
||||
set_error("file::set_size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
void set_size(size_type s)
|
||||
bool set_size(size_type s)
|
||||
{
|
||||
size_type pos = tell();
|
||||
seek(s, seek_begin);
|
||||
if (FALSE == ::SetEndOfFile(m_file_handle))
|
||||
throw_exception("file::set_size");
|
||||
|
||||
seek(pos, seek_begin);
|
||||
{
|
||||
set_error("file::set_size");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_type seek(size_type pos, seek_mode from_where)
|
||||
|
@ -261,7 +270,8 @@ namespace libtorrent
|
|||
, &offs
|
||||
, from_where))
|
||||
{
|
||||
throw_exception("file::seek");
|
||||
set_error("file::seek");
|
||||
return -1;
|
||||
}
|
||||
return offs.QuadPart;
|
||||
}
|
||||
|
@ -278,7 +288,8 @@ namespace libtorrent
|
|||
, &offs
|
||||
, FILE_CURRENT))
|
||||
{
|
||||
throw_exception("file::tell");
|
||||
set_error("file::tell");
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_type pos = offs.QuadPart;
|
||||
|
@ -299,9 +310,17 @@ namespace libtorrent
|
|||
return size;
|
||||
}
|
||||
*/
|
||||
|
||||
std::string const& error() const
|
||||
{
|
||||
if (!m_error) m_error.reset(new std::string);
|
||||
return *m_error;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
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());
|
||||
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()
|
||||
|
@ -350,9 +369,9 @@ namespace libtorrent
|
|||
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)
|
||||
|
@ -364,4 +383,9 @@ namespace libtorrent
|
|||
{
|
||||
return m_impl->tell();
|
||||
}
|
||||
|
||||
std::string const& file::error() const
|
||||
{
|
||||
return m_impl->error();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,8 +472,10 @@ namespace libtorrent
|
|||
#endif
|
||||
if (allocate_files)
|
||||
{
|
||||
std::string error;
|
||||
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())
|
||||
f->set_size(file_iter->size);
|
||||
}
|
||||
|
@ -829,21 +831,20 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
int buf_pos = 0;
|
||||
std::string error;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (!in->error().empty())
|
||||
{
|
||||
m_error = in->error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(in->error().empty());
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
|
||||
TORRENT_ASSERT(slices[0].offset == 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;
|
||||
|
||||
file_offset = 0;
|
||||
std::string error;
|
||||
in = m_files.open_file(
|
||||
this, path, file::in);
|
||||
this, path, file::in, error);
|
||||
if (!in)
|
||||
{
|
||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
||||
return -1;
|
||||
}
|
||||
if (!in->error().empty())
|
||||
{
|
||||
m_error = in->error();
|
||||
m_error = "failed to open file ";
|
||||
m_error += path.string();
|
||||
m_error += ": ";
|
||||
m_error += error;
|
||||
return -1;
|
||||
}
|
||||
TORRENT_ASSERT(in->error().empty());
|
||||
in->seek(file_iter->file_base);
|
||||
}
|
||||
}
|
||||
|
@ -981,19 +982,19 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
fs::path p(m_save_path / file_iter->path);
|
||||
std::string error;
|
||||
boost::shared_ptr<file> out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
this, p, file::out | file::in, error);
|
||||
|
||||
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;
|
||||
}
|
||||
if (!out->error().empty())
|
||||
{
|
||||
m_error = out->error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(out->error().empty());
|
||||
TORRENT_ASSERT(file_offset < file_iter->size);
|
||||
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));
|
||||
fs::path p = m_save_path / file_iter->path;
|
||||
file_offset = 0;
|
||||
std::string error;
|
||||
out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
this, p, file::out | file::in, error);
|
||||
|
||||
if (!out)
|
||||
{
|
||||
m_error = "failed to open file " + (m_save_path / file_iter->path).string();
|
||||
return -1;
|
||||
}
|
||||
if (!out->error().empty())
|
||||
{
|
||||
m_error = out->error();
|
||||
m_error = "failed to open file ";
|
||||
m_error += p.string();
|
||||
m_error += ": ";
|
||||
m_error += error;
|
||||
return -1;
|
||||
}
|
||||
TORRENT_ASSERT(out->error().empty());
|
||||
|
||||
out->seek(file_iter->file_base);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue