boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p, file::open_mode m) { assert(st != 0); assert(p.is_complete()); assert(m == file::in || m == (file::in | file::out)); boost::mutex::scoped_lock l(m_mutex); typedef nth_index<file_set, 0>::type path_view; path_view& pt = get<0>(m_files); path_view::iterator i = pt.find(p); if (i != pt.end()) { lru_file_entry e = *i; e.last_use = time_now(); if (e.key != st) { // 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() + ")"); } e.key = st; if ((e.mode & m) != m) { // close the file before we open it with // the new read/write privilages i->file_ptr.reset(); assert(e.file_ptr.unique()); e.file_ptr.reset(); e.file_ptr.reset(new file(p, m)); e.mode = m; } pt.replace(i, e); return e.file_ptr; } // the file is not in our cache if ((int)m_files.size() >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it typedef nth_index<file_set, 1>::type lru_view; lru_view& lt = get<1>(m_files); lru_view::iterator i = lt.begin(); // the first entry in this view is the least recently used 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))); e.mode = m; e.key = st; e.file_path = p; pt.insert(e); return e.file_ptr; }
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p , file::open_mode m, error_code& ec) { TORRENT_ASSERT(st != 0); TORRENT_ASSERT(p.is_complete()); TORRENT_ASSERT(m == file::in || m == (file::in | file::out)); boost::mutex::scoped_lock l(m_mutex); typedef nth_index<file_set, 0>::type path_view; path_view& pt = get<0>(m_files); path_view::iterator i = pt.find(p); if (i != pt.end()) { lru_file_entry e = *i; e.last_use = time_now(); if (e.key != st && (e.mode != file::in || m != file::in)) { // this means that another instance of the storage // is using the exact same file. #if BOOST_VERSION >= 103500 ec = error_code(errors::file_collision, libtorrent_category); #endif return boost::shared_ptr<file>(); } e.key = st; if ((e.mode & m) != m) { // close the file before we open it with // the new read/write privilages i->file_ptr.reset(); TORRENT_ASSERT(e.file_ptr.unique()); e.file_ptr->close(); if (!e.file_ptr->open(p, m, ec)) { m_files.erase(i); return boost::shared_ptr<file>(); } TORRENT_ASSERT(e.file_ptr->is_open()); e.mode = m; } pt.replace(i, e); return e.file_ptr; } // the file is not in our cache if ((int)m_files.size() >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it typedef nth_index<file_set, 1>::type lru_view; lru_view& lt = get<1>(m_files); lru_view::iterator i = lt.begin(); // the first entry in this view is the least recently used TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); lt.erase(i); } lru_file_entry e; e.file_ptr.reset(new (std::nothrow)file); if (!e.file_ptr) { ec = error_code(ENOMEM, get_posix_category()); return e.file_ptr; } if (!e.file_ptr->open(p, m, ec)) return boost::shared_ptr<file>(); e.mode = m; e.key = st; e.file_path = p; pt.insert(e); TORRENT_ASSERT(e.file_ptr->is_open()); return e.file_ptr; }