示例#1
0
 void join()
 {
     if (get_id() == GetCurrentThreadId())
         throw system_error(EDEADLK, generic_category());
     if (mHandle == _STD_THREAD_INVALID_HANDLE)
         throw system_error(ESRCH, generic_category());
     if (!joinable())
         throw system_error(EINVAL, generic_category());
     WaitForSingleObject(mHandle, INFINITE);
     CloseHandle(mHandle);
     mHandle = _STD_THREAD_INVALID_HANDLE;
     mThreadId.clear();
 }
示例#2
0
const error_category&
posix_category() {
#ifdef LLVM_ON_WIN32
  return generic_category();
#else
  return system_category();
#endif
}
示例#3
0
	int posix_storage::readv(session_settings const&
		, span<iovec_t const> bufs
		, piece_index_t const piece, int const offset
		, storage_error& error)
	{
		return readwritev(files(), bufs, piece, offset, error
			, [this](file_index_t const file_index
				, std::int64_t const file_offset
				, span<iovec_t const> vec, storage_error& ec)
		{
			if (files().pad_file_at(file_index))
			{
				// reading from a pad file yields zeroes
				clear_bufs(vec);
				return bufs_size(vec);
			}

			FILE* const f = open_file(file_index, open_mode::read_only
				, file_offset, ec);
			if (ec.ec) return -1;

			// set this unconditionally in case the upper layer would like to treat
			// short reads as errors
			ec.operation = operation_t::file_read;

			int ret = 0;
			for (auto buf : vec)
			{
				int const r = static_cast<int>(fread(buf.data(), 1
					, static_cast<std::size_t>(buf.size()), f));
				if (r == 0)
				{
					ec.ec.assign(errno, generic_category());
					break;
				}
				ret += r;

				// the file may be shorter than we think
				if (r < buf.size()) break;
			}

			fclose(f);

			// we either get an error or 0 or more bytes read
			TORRENT_ASSERT(ec.ec || ret > 0);
			TORRENT_ASSERT(ret <= bufs_size(vec));

			if (ec.ec)
			{
				ec.file(file_index);
				return -1;
			}

			return ret;
		});
	}
示例#4
0
	address bind_to_device(io_service& ios, Socket& sock
		, bool ipv4, char const* device_name, int port, error_code& ec)
	{
		boost::asio::ip::tcp::endpoint bind_ep(address_v4::any(), port);

		address ip = address::from_string(device_name, ec);
		if (!ec)
		{
			bind_ep.address(ip);
			// it appears to be an IP. Just bind to that address
			sock.bind(bind_ep, ec);
			return bind_ep.address();
		}

		ec.clear();

#ifdef SO_BINDTODEVICE
		// try to use SO_BINDTODEVICE here, if that exists. If it fails,
		// fall back to the mechanism we have below
		sock.set_option(bind_to_device_opt(device_name), ec);
		if (ec)
#endif
		{
			ec.clear();
			// TODO: 2 this could be done more efficiently by just looking up
			// the interface with the given name, maybe even with if_nametoindex()
			std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec);
			if (ec) return bind_ep.address();

			bool found = false;

			for (int i = 0; i < int(ifs.size()); ++i)
			{
				// we're looking for a specific interface, and its address
				// (which must be of the same family as the address we're
				// connecting to)
				if (strcmp(ifs[i].name, device_name) != 0) continue;
				if (ifs[i].interface_address.is_v4() != ipv4)
					continue;

				bind_ep.address(ifs[i].interface_address);
				found = true;
				break;
			}

			if (!found)
			{
				ec = error_code(boost::system::errc::no_such_device, generic_category());
				return bind_ep.address();
			}
		}
		sock.bind(bind_ep, ec);
		return bind_ep.address();
	}
示例#5
0
	int posix_storage::writev(session_settings const&
		, span<iovec_t const> bufs
		, piece_index_t const piece, int const offset
		, storage_error& error)
	{
		return readwritev(files(), bufs, piece, offset, error
			, [this](file_index_t const file_index
				, std::int64_t const file_offset
				, span<iovec_t const> vec, storage_error& ec)
		{
			if (files().pad_file_at(file_index))
			{
				// writing to a pad-file is a no-op
				return bufs_size(vec);
			}

			FILE* const f = open_file(file_index, open_mode::write
				, file_offset, ec);
			if (ec.ec) return -1;

			// set this unconditionally in case the upper layer would like to treat
			// short reads as errors
			ec.operation = operation_t::file_write;

			int ret = 0;
			for (auto buf : vec)
			{
				auto const r = static_cast<int>(fwrite(buf.data(), 1
					, static_cast<std::size_t>(buf.size()), f));
				if (r != buf.size())
				{
					ec.ec.assign(errno, generic_category());
					break;
				}
				ret += r;
			}

			fclose(f);

			// invalidate our stat cache for this file, since
			// we're writing to it
			m_stat_cache.set_dirty(file_index);

			if (ec)
			{
				ec.file(file_index);
				return -1;
			}

			return ret;
		});
	}
示例#6
0
	// this has to be thread safe and atomic. i.e. on posix systems it has to be
	// turned into a series of pread() calls
	std::int64_t file::readv(std::int64_t file_offset, span<iovec_t const> bufs
		, error_code& ec, open_mode_t flags)
	{
		if (m_file_handle == INVALID_HANDLE_VALUE)
		{
#ifdef TORRENT_WINDOWS
			ec = error_code(ERROR_INVALID_HANDLE, system_category());
#else
			ec = error_code(boost::system::errc::bad_file_descriptor, generic_category());
#endif
			return -1;
		}
		TORRENT_ASSERT((m_open_mode & open_mode::rw_mask) == open_mode::read_only
			|| (m_open_mode & open_mode::rw_mask) == open_mode::read_write);
		TORRENT_ASSERT(!bufs.empty());
		TORRENT_ASSERT(is_open());

#if TORRENT_USE_PREADV
		TORRENT_UNUSED(flags);
		std::int64_t ret = iov(&::preadv, native_handle(), file_offset, bufs, ec);
#else

		// there's no point in coalescing single buffer writes
		if (bufs.size() == 1)
		{
			flags &= ~open_mode::coalesce_buffers;
		}

		iovec_t tmp;
		span<iovec_t const> tmp_bufs = bufs;
		if (flags & open_mode::coalesce_buffers)
		{
			if (!coalesce_read_buffers(tmp_bufs, tmp))
				// ok, that failed, don't coalesce this read
				flags &= ~open_mode::coalesce_buffers;
		}

#if TORRENT_USE_PREAD
		std::int64_t ret = iov(&::pread, native_handle(), file_offset, tmp_bufs, ec);
#else
		std::int64_t ret = iov(&::read, native_handle(), file_offset, tmp_bufs, ec);
#endif

		if (flags & open_mode::coalesce_buffers)
			coalesce_read_buffers_end(bufs
				, tmp.data(), !ec);

#endif
		return ret;
	}
示例#7
0
文件: error_code.hpp 项目: gijs/hexer
 void clear()
 {
   m_val = 0;
   m_cat = &generic_category();
 }
示例#8
0
文件: error_code.hpp 项目: gijs/hexer
  namespace system
  {

    class error_code;
    class error_condition;

    //  "Concept" helpers  ---------------------------------------------------//

    template< class T >
    struct is_error_code_enum { static const bool value = false; };

    template< class T >
    struct is_error_condition_enum { static const bool value = false; };

    //  generic error_conditions  --------------------------------------------//

    namespace errc
    {
      enum errc_t
      {
        success = 0,
        address_family_not_supported = EAFNOSUPPORT,
        address_in_use = EADDRINUSE,
        address_not_available = EADDRNOTAVAIL,
        already_connected = EISCONN,
        argument_list_too_long = E2BIG,
        argument_out_of_domain = EDOM,
        bad_address = EFAULT,
        bad_file_descriptor = EBADF,
        bad_message = EBADMSG,
        broken_pipe = EPIPE,
        connection_aborted = ECONNABORTED,
        connection_already_in_progress = EALREADY,
        connection_refused = ECONNREFUSED,
        connection_reset = ECONNRESET,
        cross_device_link = EXDEV,
        destination_address_required = EDESTADDRREQ,
        device_or_resource_busy = EBUSY,
        directory_not_empty = ENOTEMPTY,
        executable_format_error = ENOEXEC,
        file_exists = EEXIST,
        file_too_large = EFBIG,
        filename_too_long = ENAMETOOLONG,
        function_not_supported = ENOSYS,
        host_unreachable = EHOSTUNREACH,
        identifier_removed = EIDRM,
        illegal_byte_sequence = EILSEQ,
        inappropriate_io_control_operation = ENOTTY,
        interrupted = EINTR,
        invalid_argument = EINVAL,
        invalid_seek = ESPIPE,
        io_error = EIO,
        is_a_directory = EISDIR,
        message_size = EMSGSIZE,
        network_down = ENETDOWN,
        network_reset = ENETRESET,
        network_unreachable = ENETUNREACH,
        no_buffer_space = ENOBUFS,
        no_child_process = ECHILD,
        no_link = ENOLINK,
        no_lock_available = ENOLCK,
        no_message_available = ENODATA,
        no_message = ENOMSG,
        no_protocol_option = ENOPROTOOPT,
        no_space_on_device = ENOSPC,
        no_stream_resources = ENOSR,
        no_such_device_or_address = ENXIO,
        no_such_device = ENODEV,
        no_such_file_or_directory = ENOENT,
        no_such_process = ESRCH,
        not_a_directory = ENOTDIR,
        not_a_socket = ENOTSOCK,
        not_a_stream = ENOSTR,
        not_connected = ENOTCONN,
        not_enough_memory = ENOMEM,
        not_supported = ENOTSUP,
        operation_canceled = ECANCELED,
        operation_in_progress = EINPROGRESS,
        operation_not_permitted = EPERM,
        operation_not_supported = EOPNOTSUPP,
        operation_would_block = EWOULDBLOCK,
        owner_dead = EOWNERDEAD,
        permission_denied = EACCES,
        protocol_error = EPROTO,
        protocol_not_supported = EPROTONOSUPPORT,
        read_only_file_system = EROFS,
        resource_deadlock_would_occur = EDEADLK,
        resource_unavailable_try_again = EAGAIN,
        result_out_of_range = ERANGE,
        state_not_recoverable = ENOTRECOVERABLE,
        stream_timeout = ETIME,
        text_file_busy = ETXTBSY,
        timed_out = ETIMEDOUT,
        too_many_files_open_in_system = ENFILE,
        too_many_files_open = EMFILE,
        too_many_links = EMLINK,
        too_many_symbolic_link_levels = ELOOP,
        value_too_large = EOVERFLOW,
        wrong_protocol_type = EPROTOTYPE
      };

    } // namespace errc

# ifndef BOOST_SYSTEM_NO_DEPRECATED
    namespace posix = errc;
    namespace posix_error = errc;
# endif

    template<> struct is_error_condition_enum<errc::errc_t>
      { static const bool value = true; };


    //  ----------------------------------------------------------------------//

    //  Operating system specific interfaces  --------------------------------//


    //  The interface is divided into general and system-specific portions to
    //  meet these requirements:
    //
    //  * Code calling an operating system API can create an error_code with
    //    a single category (system_category), even for POSIX-like operating
    //    systems that return some POSIX errno values and some native errno
    //    values. This code should not have to pay the cost of distinguishing
    //    between categories, since it is not yet known if that is needed.
    //
    //  * Users wishing to write system-specific code should be given enums for
    //    at least the common error cases.
    //
    //  * System specific code should fail at compile time if moved to another
    //    operating system.

    //  The system specific portions of the interface are located in headers
    //  with names reflecting the operating system. For example,
    //
    //       <boost/system/cygwin_error.hpp>
    //       <boost/system/linux_error.hpp>
    //       <boost/system/windows_error.hpp>
    //
    //  These headers are effectively empty for compiles on operating systems
    //  where they are not applicable.

    //  ----------------------------------------------------------------------//

    //  class error_category  ------------------------------------------------//

    class error_category : public noncopyable
    {
    public:
      virtual ~error_category(){}

      virtual const char *     name() const = 0;
      virtual std::string      message( int ev ) const = 0;
      virtual error_condition  default_error_condition( int ev ) const;
      virtual bool             equivalent( int code, 
                                           const error_condition & condition ) const;
      virtual bool             equivalent( const error_code & code,
                                           int condition ) const;

      bool operator==(const error_category & rhs) const { return this == &rhs; }
      bool operator!=(const error_category & rhs) const { return this != &rhs; }
      bool operator<( const error_category & rhs ) const
      {
        return std::less<const error_category*>()( this, &rhs );
      }
    };

    //  predefined error categories  -----------------------------------------//

    BOOST_SYSTEM_DECL const error_category &  system_category();
    BOOST_SYSTEM_DECL const error_category &  generic_category();

    //  deprecated synonyms --------------------------------------------------//

# ifndef BOOST_SYSTEM_NO_DEPRECATED
    inline const error_category &  get_system_category() { return system_category(); }
    inline const error_category &  get_generic_category() { return generic_category(); }
    inline const error_category &  get_posix_category() { return generic_category(); }
    static const error_category &  posix_category = generic_category();
    static const error_category &  errno_ecat     = generic_category();
    static const error_category &  native_ecat    = system_category();
# endif

    //  class error_condition  -----------------------------------------------//

    //  error_conditions are portable, error_codes are system or library specific

    class error_condition
    {
    public:

      // constructors:
      error_condition() : m_val(0), m_cat(&generic_category()) {}
      error_condition( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}

      template <class ErrorConditionEnum>
        error_condition(ErrorConditionEnum e,
          typename hexerboost::enable_if<is_error_condition_enum<ErrorConditionEnum> >::type* = 0)
      {
        *this = make_error_condition(e);
      }

      // modifiers:

      void assign( int val, const error_category & cat )
      { 
        m_val = val;
        m_cat = &cat;
      }
                                             
      template<typename ErrorConditionEnum>
        typename hexerboost::enable_if<is_error_condition_enum<ErrorConditionEnum>, error_condition>::type &
          operator=( ErrorConditionEnum val )
      { 
        *this = make_error_condition(val);
        return *this;
      }

      void clear()
      {
        m_val = 0;
        m_cat = &generic_category();
      }

      // observers:
      int                     value() const    { return m_val; }
      const error_category &  category() const { return *m_cat; }
      std::string             message() const  { return m_cat->message(value()); }

      typedef void (*unspecified_bool_type)();
      static void unspecified_bool_true() {}

      operator unspecified_bool_type() const  // true if error
      { 
        return m_val == 0 ? 0 : unspecified_bool_true;
      }

      bool operator!() const  // true if no error
      {
        return m_val == 0;
      }

      // relationals:
      //  the more symmetrical non-member syntax allows enum
      //  conversions work for both rhs and lhs.
      inline friend bool operator==( const error_condition & lhs,
                                     const error_condition & rhs )
      {
        return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
      }                  

      inline friend bool operator<( const error_condition & lhs,
                                    const error_condition & rhs )
        //  the more symmetrical non-member syntax allows enum
        //  conversions work for both rhs and lhs.
      {
        return lhs.m_cat < rhs.m_cat
          || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
      }

    private:
      int                     m_val;
      const error_category *  m_cat;

    };

    //  class error_code  ----------------------------------------------------//

    //  We want error_code to be a value type that can be copied without slicing
    //  and without requiring heap allocation, but we also want it to have
    //  polymorphic behavior based on the error category. This is achieved by
    //  abstract base class error_category supplying the polymorphic behavior,
    //  and error_code containing a pointer to an object of a type derived
    //  from error_category.
    class error_code
    {
    public:

      // constructors:
      error_code() : m_val(0), m_cat(&system_category()) {}
      error_code( int val, const error_category & cat ) : m_val(val), m_cat(&cat) {}

      template <class ErrorCodeEnum>
        error_code(ErrorCodeEnum e,
          typename hexerboost::enable_if<is_error_code_enum<ErrorCodeEnum> >::type* = 0)
      {
        *this = make_error_code(e);
      }

      // modifiers:
      void assign( int val, const error_category & cat )
      { 
        m_val = val;
        m_cat = &cat;
      }
                                             
      template<typename ErrorCodeEnum>
        typename hexerboost::enable_if<is_error_code_enum<ErrorCodeEnum>, error_code>::type &
          operator=( ErrorCodeEnum val )
      { 
        *this = make_error_code(val);
        return *this;
      }

      void clear()
      {
        m_val = 0;
        m_cat = &system_category();
      }

      // observers:
      int                     value() const    { return m_val; }
      const error_category &  category() const { return *m_cat; }
      error_condition         default_error_condition() const  { return m_cat->default_error_condition(value()); }
      std::string             message() const  { return m_cat->message(value()); }

      typedef void (*unspecified_bool_type)();
      static void unspecified_bool_true() {}

      operator unspecified_bool_type() const  // true if error
      { 
        return m_val == 0 ? 0 : unspecified_bool_true;
      }

      bool operator!() const  // true if no error
      {
        return m_val == 0;
      }

      // relationals:
      inline friend bool operator==( const error_code & lhs,
                                     const error_code & rhs )
        //  the more symmetrical non-member syntax allows enum
        //  conversions work for both rhs and lhs.
      {
        return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val;
      }

      inline friend bool operator<( const error_code & lhs,
                                    const error_code & rhs )
        //  the more symmetrical non-member syntax allows enum
        //  conversions work for both rhs and lhs.
      {
        return lhs.m_cat < rhs.m_cat
          || (lhs.m_cat == rhs.m_cat && lhs.m_val < rhs.m_val);
      }
                  
      private:
      int                     m_val;
      const error_category *  m_cat;

    };

    //  predefined error_code object used as "throw on error" tag
# ifndef BOOST_SYSTEM_NO_DEPRECATED
    BOOST_SYSTEM_DECL extern error_code throws;
# endif

    //  Moving from a "throws" object to a "throws" function without breaking
    //  existing code is a bit of a problem. The workaround is to place the
    //  "throws" function in namespace hexerboost rather than namespace hexerboost::system.

  }  // namespace system
示例#9
0
文件: error_code.hpp 项目: gijs/hexer
 inline const error_category &  get_posix_category() { return generic_category(); }
示例#10
0
文件: error_code.hpp 项目: gijs/hexer
 // constructors:
 error_condition() : m_val(0), m_cat(&generic_category()) {}
示例#11
0
	address bind_socket_to_device(io_service& ios, Socket& sock
		, boost::asio::ip::tcp const& protocol
		, char const* device_name, int port, error_code& ec)
	{
		tcp::endpoint bind_ep(address_v4::any(), std::uint16_t(port));

		address ip = make_address(device_name, ec);
		if (!ec)
		{
#if TORRENT_USE_IPV6
			// this is to cover the case where "0.0.0.0" is considered any IPv4 or
			// IPv6 address. If we're asking to be bound to an IPv6 address and
			// providing 0.0.0.0 as the device, turn it into "::"
			if (ip == address_v4::any() && protocol == boost::asio::ip::tcp::v6())
				ip = address_v6::any();
#endif
			bind_ep.address(ip);
			// it appears to be an IP. Just bind to that address
			sock.bind(bind_ep, ec);
			return bind_ep.address();
		}

		ec.clear();

#if TORRENT_HAS_BINDTODEVICE
		// try to use SO_BINDTODEVICE here, if that exists. If it fails,
		// fall back to the mechanism we have below
		sock.set_option(aux::bind_to_device(device_name), ec);
		if (ec)
#endif
		{
			ec.clear();
			// TODO: 2 this could be done more efficiently by just looking up
			// the interface with the given name, maybe even with if_nametoindex()
			std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec);
			if (ec) return bind_ep.address();

			bool found = false;

			for (auto const& iface : ifs)
			{
				// we're looking for a specific interface, and its address
				// (which must be of the same family as the address we're
				// connecting to)
				if (std::strcmp(iface.name, device_name) != 0) continue;
				if (iface.interface_address.is_v4() != (protocol == boost::asio::ip::tcp::v4()))
					continue;

				bind_ep.address(iface.interface_address);
				found = true;
				break;
			}

			if (!found)
			{
				ec = error_code(boost::system::errc::no_such_device, generic_category());
				return bind_ep.address();
			}
		}
		sock.bind(bind_ep, ec);
		return bind_ep.address();
	}
示例#12
0
void __throw_system_error(int c) {
  throw system_error(error_code(c, generic_category()));
}
示例#13
0
	file_handle file_pool::open_file(storage_index_t st, std::string const& p
		, file_index_t const file_index, file_storage const& fs, int m, error_code& ec)
	{
		// potentially used to hold a reference to a file object that's
		// about to be destructed. If we have such object we assign it to
		// this member to be destructed after we release the std::mutex. On some
		// operating systems (such as OSX) closing a file may take a long
		// time. We don't want to hold the std::mutex for that.
		file_handle defer_destruction;

		std::unique_lock<std::mutex> l(m_mutex);

#if TORRENT_USE_ASSERTS
		// we're not allowed to open a file
		// from a deleted storage!
		TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end()
			, std::make_pair(fs.name(), static_cast<void const*>(&fs)))
			== m_deleted_storages.end());
#endif

		TORRENT_ASSERT(is_complete(p));
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		auto const i = m_files.find(std::make_pair(st, file_index));
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = aux::time_now();

			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if ((((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
				|| (e.mode & file::random_access) != (m & file::random_access))
			{
				file_handle new_file = std::make_shared<file>();

				std::string full_path = fs.file_path(file_index, p);
				if (!new_file->open(full_path, m, ec))
					return file_handle();
#ifdef TORRENT_WINDOWS
				if (m_low_prio_io)
					set_low_priority(new_file);
#endif

				TORRENT_ASSERT(new_file->is_open());
				defer_destruction = std::move(e.file_ptr);
				e.file_ptr = std::move(new_file);
				e.mode = m;
			}
			return e.file_ptr;
		}

		lru_file_entry e;
		e.file_ptr = std::make_shared<file>();
		if (!e.file_ptr)
		{
			ec = error_code(boost::system::errc::not_enough_memory, generic_category());
			return file_handle();
		}
		std::string full_path = fs.file_path(file_index, p);
		if (!e.file_ptr->open(full_path, m, ec))
			return file_handle();
#ifdef TORRENT_WINDOWS
		if (m_low_prio_io)
			set_low_priority(e.file_ptr);
#endif
		e.mode = m;
		file_handle file_ptr = e.file_ptr;
		m_files.insert(std::make_pair(std::make_pair(st, file_index), e));
		TORRENT_ASSERT(file_ptr->is_open());

		if (int(m_files.size()) >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest(l);
		}
		return file_ptr;
	}
示例#14
0
	// This has to be thread safe, i.e. atomic.
	// that means, on posix this has to be turned into a series of
	// pwrite() calls
	std::int64_t file::writev(std::int64_t file_offset, span<iovec_t const> bufs
		, error_code& ec, open_mode_t flags)
	{
		if (m_file_handle == INVALID_HANDLE_VALUE)
		{
#ifdef TORRENT_WINDOWS
			ec = error_code(ERROR_INVALID_HANDLE, system_category());
#else
			ec = error_code(boost::system::errc::bad_file_descriptor, generic_category());
#endif
			return -1;
		}
		TORRENT_ASSERT((m_open_mode & open_mode::rw_mask) == open_mode::write_only
			|| (m_open_mode & open_mode::rw_mask) == open_mode::read_write);
		TORRENT_ASSERT(!bufs.empty());
		TORRENT_ASSERT(is_open());

		ec.clear();

#if TORRENT_USE_PREADV
		TORRENT_UNUSED(flags);

		std::int64_t ret = iov(&::pwritev, native_handle(), file_offset, bufs, ec);
#else

		// there's no point in coalescing single buffer writes
		if (bufs.size() == 1)
		{
			flags &= ~open_mode::coalesce_buffers;
		}

		iovec_t tmp;
		if (flags & open_mode::coalesce_buffers)
		{
			if (!coalesce_write_buffers(bufs, tmp))
				// ok, that failed, don't coalesce writes
				flags &= ~open_mode::coalesce_buffers;
		}

#if TORRENT_USE_PREAD
		std::int64_t ret = iov(&::pwrite, native_handle(), file_offset, bufs, ec);
#else
		std::int64_t ret = iov(&::write, native_handle(), file_offset, bufs, ec);
#endif

		if (flags & open_mode::coalesce_buffers)
			delete[] tmp.data();

#endif
#if TORRENT_USE_FDATASYNC \
	&& !defined F_NOCACHE && \
	!defined DIRECTIO_ON
		if (m_open_mode & open_mode::no_cache)
		{
			if (::fdatasync(native_handle()) != 0
				&& errno != EINVAL
				&& errno != ENOSYS)
			{
				ec.assign(errno, system_category());
			}
		}
#endif
		return ret;
	}
示例#15
0
文件: error_code.hpp 项目: gijs/hexer
 //  explicit conversion:
 inline error_code make_error_code( errc_t e )
   { return error_code( e, generic_category() ); }
示例#16
0
    void
    do_visit(
        std::size_t N,
        std::size_t blockSize,
        float loadFactor)
    {
        using key_type = std::uint32_t;

        error_code ec;
        test_store ts{sizeof(key_type), blockSize, loadFactor};

        // File not present
        visit(ts.dp,
            [&](void const* key, std::size_t keySize,
                void const* data, std::size_t dataSize,
                error_code& ec)
            {
            }, no_progress{}, ec);
        if(! BEAST_EXPECTS(ec ==
                errc::no_such_file_or_directory, ec.message()))
            return;
        ec = {};

        ts.create(ec);
        if(! BEAST_EXPECTS(! ec, ec.message()))
            return;
        ts.open(ec);
        if(! BEAST_EXPECTS(! ec, ec.message()))
            return;
        std::unordered_map<key_type, std::size_t> map;
        // Insert
        for(std::size_t i = 0; i < N; ++i)
        {
            auto const item = ts[i];
            key_type const k =         item.key[0]         +
                (static_cast<key_type>(item.key[1]) <<  8) +
                (static_cast<key_type>(item.key[2]) << 16) +
                (static_cast<key_type>(item.key[3]) << 24);
            map[k] = i;
            ts.db.insert(item.key, item.data, item.size, ec);
            if(! BEAST_EXPECTS(! ec, ec.message()))
                return;
        }
        ts.close(ec);
        if(! BEAST_EXPECTS(! ec, ec.message()))
            return;
        // Visit
        visit(ts.dp,
            [&](void const* key, std::size_t keySize,
                void const* data, std::size_t dataSize,
                error_code& ec)
            {
                auto const fail =
                    [&ec]
                    {
                        ec = error_code{
                            errc::invalid_argument, generic_category()};
                    };
                if(! BEAST_EXPECT(keySize == sizeof(key_type)))
                    return fail();
                auto const p =
                    reinterpret_cast<std::uint8_t const*>(key);
                key_type const k =         p[0]         +
                    (static_cast<key_type>(p[1]) <<  8) +
                    (static_cast<key_type>(p[2]) << 16) +
                    (static_cast<key_type>(p[3]) << 24);
                auto const it = map.find(k);
                if(it == map.end())
                    return fail();
                auto const item = ts[it->second];
                if(! BEAST_EXPECT(dataSize == item.size))
                    return fail();
                auto const result =
                    std::memcmp(data, item.data, item.size);
                if(result != 0)
                    return fail();
            }, no_progress{}, ec);
        if(! BEAST_EXPECTS(! ec, ec.message()))
            return;
    }
示例#17
0
	FILE* posix_storage::open_file(file_index_t idx, open_mode_t const mode
		, std::int64_t const offset, storage_error& ec)
	{
		std::string const fn = files().file_path(idx, m_save_path);

		char const* mode_str = (mode & open_mode::write)
			? "rb+" : "rb";

		FILE* f = fopen(fn.c_str(), mode_str);
		if (f == nullptr)
		{
			ec.ec.assign(errno, generic_category());

			// if we fail to open a file for writing, and the error is ENOENT,
			// it is likely because the directory we're creating the file in
			// does not exist. Create the directory and try again.
			if ((mode & open_mode::write)
				&& ec.ec == boost::system::errc::no_such_file_or_directory)
			{
				// this means the directory the file is in doesn't exist.
				// so create it
				ec.ec.clear();
				create_directories(parent_path(fn), ec.ec);

				if (ec.ec)
				{
					ec.file(idx);
					ec.operation = operation_t::mkdir;
					return nullptr;
				}

				// now that we've created the directories, try again
				// and make sure we create the file this time ("r+") opens for
				// reading and writing, but doesn't create the file. "w+" creates
				// the file and truncates it
				f = fopen(fn.c_str(), "wb+");
				if (f == nullptr)
				{
					ec.ec.assign(errno, generic_category());
					ec.file(idx);
					ec.operation = operation_t::file_open;
					return nullptr;
				}
			}
			else
			{
				ec.file(idx);
				ec.operation = operation_t::file_open;
				return nullptr;
			}
		}

#ifdef TORRENT_WINDOWS
#define fseek _fseeki64
#endif

		if (offset != 0)
		{
			if (fseek(f, offset, SEEK_SET) != 0)
			{
				ec.ec.assign(errno, generic_category());
				ec.file(idx);
				ec.operation = operation_t::file_seek;
				fclose(f);
				return nullptr;
			}
		}

		return f;
	}
示例#18
0
文件: error_code.hpp 项目: gijs/hexer
 //  implicit conversion:
 inline error_condition make_error_condition( errc_t e )
   { return error_condition( e, generic_category() ); }
示例#19
0
	file_handle file_pool::open_file(void* st, std::string const& p
		, int file_index, file_storage const& fs, int m, error_code& ec)
	{
		// potentially used to hold a reference to a file object that's
		// about to be destructed. If we have such object we assign it to
		// this member to be destructed after we release the std::mutex. On some
		// operating systems (such as OSX) closing a file may take a long
		// time. We don't want to hold the std::mutex for that.
		file_handle defer_destruction;

		std::unique_lock<std::mutex> l(m_mutex);

#if TORRENT_USE_ASSERTS
		// we're not allowed to open a file
		// from a deleted storage!
		TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end()
			, std::make_pair(fs.name(), static_cast<void const*>(&fs)))
			== m_deleted_storages.end());
#endif

		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(is_complete(p));
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		file_set::iterator i = m_files.find(std::make_pair(st, file_index));
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = aux::time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
				ec = errors::file_collision;
				return file_handle();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if ((((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
				|| (e.mode & file::random_access) != (m & file::random_access))
			{
				// close the file before we open it with
				// the new read/write privileges, since windows may
				// file opening a file twice. However, since there may
				// be outstanding operations on it, we can't close the
				// file, we can only delete our reference to it.
				// if this is the only reference to the file, it will be closed
				defer_destruction = e.file_ptr;
				e.file_ptr = boost::make_shared<file>();

				std::string full_path = fs.file_path(file_index, p);
				if (!e.file_ptr->open(full_path, m, ec))
				{
					m_files.erase(i);
					return file_handle();
				}
#ifdef TORRENT_WINDOWS
				if (m_low_prio_io)
					set_low_priority(e.file_ptr);
#endif

				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			return e.file_ptr;
		}

		lru_file_entry e;
		e.file_ptr = boost::make_shared<file>();
		if (!e.file_ptr)
		{
			ec = error_code(boost::system::errc::not_enough_memory, generic_category());
			return e.file_ptr;
		}
		std::string full_path = fs.file_path(file_index, p);
		if (!e.file_ptr->open(full_path, m, ec))
			return file_handle();
#ifdef TORRENT_WINDOWS
		if (m_low_prio_io)
			set_low_priority(e.file_ptr);
#endif
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(std::make_pair(st, file_index), e));
		TORRENT_ASSERT(e.file_ptr->is_open());

		file_handle file_ptr = 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
			remove_oldest(l);
		}
		return file_ptr;
	}