Esempio n. 1
0
	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;
	}
Esempio n. 2
0
	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;
	}