updated file_win and file_pool error handling

This commit is contained in:
Arvid Norberg 2008-02-25 04:41:21 +00:00
parent 480b63b516
commit 9f44c577d7
6 changed files with 134 additions and 93 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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);
}