mirror of
https://github.com/matrix-construct/construct
synced 2024-12-01 19:22:53 +01:00
ircd::server: Add preliminary write loop; minor cleanup.
This commit is contained in:
parent
d62afeb0a7
commit
368838d5a5
4 changed files with 125 additions and 41 deletions
|
@ -36,9 +36,9 @@ struct ircd::server::link
|
||||||
bool busy() const;
|
bool busy() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void discard_read();
|
||||||
const_buffer process_read_next(const const_buffer &, struct request::tag &, bool &done);
|
const_buffer process_read_next(const const_buffer &, struct request::tag &, bool &done);
|
||||||
bool process_read(const_buffer &);
|
bool process_read(const_buffer &);
|
||||||
void discard_read();
|
|
||||||
void handle_readable_success();
|
void handle_readable_success();
|
||||||
void handle_readable(const error_code &);
|
void handle_readable(const error_code &);
|
||||||
void wait_readable();
|
void wait_readable();
|
||||||
|
|
|
@ -85,16 +85,21 @@ struct ircd::server::request::tag
|
||||||
{
|
{
|
||||||
server::request *request;
|
server::request *request;
|
||||||
ctx::promise<http::code> p;
|
ctx::promise<http::code> p;
|
||||||
|
size_t head_written {0};
|
||||||
|
size_t content_written {0};
|
||||||
size_t head_read {0};
|
size_t head_read {0};
|
||||||
size_t content_read {0};
|
size_t content_read {0};
|
||||||
|
|
||||||
mutable_buffer make_content_buffer() const;
|
mutable_buffer make_read_content_buffer() const;
|
||||||
mutable_buffer make_head_buffer() const;
|
mutable_buffer make_read_head_buffer() const;
|
||||||
|
|
||||||
const_buffer read_content(const const_buffer &, bool &done);
|
const_buffer read_content(const const_buffer &, bool &done);
|
||||||
const_buffer read_head(const const_buffer &, bool &done);
|
const_buffer read_head(const const_buffer &, bool &done);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
const_buffer make_write_buffer() const;
|
||||||
|
void wrote_buffer(const const_buffer &);
|
||||||
|
|
||||||
mutable_buffer make_read_buffer() const;
|
mutable_buffer make_read_buffer() const;
|
||||||
const_buffer read_buffer(const const_buffer &, bool &done);
|
const_buffer read_buffer(const const_buffer &, bool &done);
|
||||||
|
|
||||||
|
|
|
@ -2198,17 +2198,16 @@ noexcept try
|
||||||
{
|
{
|
||||||
using namespace boost::system::errc;
|
using namespace boost::system::errc;
|
||||||
|
|
||||||
reply_set = false;
|
|
||||||
switch(ec.value())
|
switch(ec.value())
|
||||||
{
|
{
|
||||||
|
case operation_canceled:
|
||||||
|
return;
|
||||||
|
|
||||||
case success:
|
case success:
|
||||||
|
reply_set = false;
|
||||||
set_handle();
|
set_handle();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case operation_canceled:
|
|
||||||
log::debug("Resolver leaving");
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw boost::system::system_error(ec);
|
throw boost::system::system_error(ec);
|
||||||
}
|
}
|
||||||
|
|
146
ircd/server.cc
146
ircd/server.cc
|
@ -214,8 +214,47 @@ const
|
||||||
{
|
{
|
||||||
assert(request);
|
assert(request);
|
||||||
return !request? mutable_buffer{}:
|
return !request? mutable_buffer{}:
|
||||||
!request->in.head.status? make_head_buffer():
|
!request->in.head.status? make_read_head_buffer():
|
||||||
make_content_buffer();
|
make_read_content_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::server::request::tag::wrote_buffer(const const_buffer &buffer)
|
||||||
|
{
|
||||||
|
assert(request);
|
||||||
|
const auto &req{*request};
|
||||||
|
if(head_written < size(req.out.head))
|
||||||
|
{
|
||||||
|
assert(data(buffer) == data(req.out.head));
|
||||||
|
head_written += size(buffer);
|
||||||
|
}
|
||||||
|
else if(content_written < size(req.out.content))
|
||||||
|
{
|
||||||
|
assert(data(buffer) == data(req.out.content));
|
||||||
|
content_written += size(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::const_buffer
|
||||||
|
ircd::server::request::tag::make_write_buffer()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
assert(request);
|
||||||
|
const auto &req{*request};
|
||||||
|
if(head_written < size(req.out.head))
|
||||||
|
{
|
||||||
|
const size_t remain{size(req.out.head) - head_written};
|
||||||
|
const const_buffer window{data(req.out.head) + head_written, remain};
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
else if(content_written < size(req.out.content))
|
||||||
|
{
|
||||||
|
const size_t remain{size(req.out.content) - content_written};
|
||||||
|
const const_buffer window{data(req.out.content) + content_written, remain};
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::const_buffer
|
ircd::const_buffer
|
||||||
|
@ -346,7 +385,7 @@ ircd::server::request::tag::read_content(const const_buffer &buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::mutable_buffer
|
ircd::mutable_buffer
|
||||||
ircd::server::request::tag::make_head_buffer()
|
ircd::server::request::tag::make_read_head_buffer()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
assert(request);
|
assert(request);
|
||||||
|
@ -372,7 +411,7 @@ const
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::mutable_buffer
|
ircd::mutable_buffer
|
||||||
ircd::server::request::tag::make_content_buffer()
|
ircd::server::request::tag::make_read_content_buffer()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
assert(request);
|
assert(request);
|
||||||
|
@ -624,8 +663,7 @@ ircd::server::link::submit(request &request)
|
||||||
queue.emplace(end(queue), request)
|
queue.emplace(end(queue), request)
|
||||||
};
|
};
|
||||||
|
|
||||||
write(*socket, request.out.head);
|
wait_writable();
|
||||||
write(*socket, request.out.content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -707,7 +745,49 @@ ircd::server::link::wait_writable()
|
||||||
void
|
void
|
||||||
ircd::server::link::handle_writable(const error_code &ec)
|
ircd::server::link::handle_writable(const error_code &ec)
|
||||||
{
|
{
|
||||||
std::cout << this << " writable: " << string(ec) << std::endl;
|
using namespace boost::system::errc;
|
||||||
|
using boost::system::system_category;
|
||||||
|
|
||||||
|
switch(ec.value())
|
||||||
|
{
|
||||||
|
case success:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case operation_canceled:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw boost::system::system_error{ec};
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &tag : queue)
|
||||||
|
{
|
||||||
|
const const_buffer buffer
|
||||||
|
{
|
||||||
|
tag.make_write_buffer()
|
||||||
|
};
|
||||||
|
|
||||||
|
if(empty(buffer))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const size_t bytes
|
||||||
|
{
|
||||||
|
write_any(*socket, buffer)
|
||||||
|
};
|
||||||
|
|
||||||
|
const const_buffer written
|
||||||
|
{
|
||||||
|
data(buffer), bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
tag.wrote_buffer(written);
|
||||||
|
|
||||||
|
if(bytes < size(buffer))
|
||||||
|
{
|
||||||
|
wait_writable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -772,32 +852,6 @@ ircd::server::link::handle_readable_success()
|
||||||
while(!queue.empty());
|
while(!queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ircd::server::link::discard_read()
|
|
||||||
{
|
|
||||||
const size_t discard
|
|
||||||
{
|
|
||||||
available(*socket)
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t discarded
|
|
||||||
{
|
|
||||||
discard_any(*socket, discard)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Shouldn't ever be hit because the read() within discard() throws
|
|
||||||
// the pending error like an eof.
|
|
||||||
log::warning("Link discarded %zu of %zu unexpected bytes",
|
|
||||||
discard,
|
|
||||||
discarded);
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
// for non-assert builds just in case; so this doesn't get loopy with
|
|
||||||
// discarding zero with an empty queue...
|
|
||||||
if(unlikely(!discard || !discarded))
|
|
||||||
throw assertive("Queue is empty and nothing to discard.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process as many read operations for one tag as possible
|
/// Process as many read operations for one tag as possible
|
||||||
bool
|
bool
|
||||||
ircd::server::link::process_read(const_buffer &overrun)
|
ircd::server::link::process_read(const_buffer &overrun)
|
||||||
|
@ -873,6 +927,32 @@ ircd::server::link::process_read_next(const const_buffer &underrun,
|
||||||
return overrun;
|
return overrun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::server::link::discard_read()
|
||||||
|
{
|
||||||
|
const size_t discard
|
||||||
|
{
|
||||||
|
available(*socket)
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t discarded
|
||||||
|
{
|
||||||
|
discard_any(*socket, discard)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Shouldn't ever be hit because the read() within discard() throws
|
||||||
|
// the pending error like an eof.
|
||||||
|
log::warning("Link discarded %zu of %zu unexpected bytes",
|
||||||
|
discard,
|
||||||
|
discarded);
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
// for non-assert builds just in case; so this doesn't get loopy with
|
||||||
|
// discarding zero with an empty queue...
|
||||||
|
if(unlikely(!discard || !discarded))
|
||||||
|
throw assertive("Queue is empty and nothing to discard.");
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::server::link::busy()
|
ircd::server::link::busy()
|
||||||
const
|
const
|
||||||
|
|
Loading…
Reference in a new issue