#include "metacube.h"
#include "server.h"
#include "mutexlock.h"
+#include "state.pb.h"
using namespace std;
+Client::Client(int sock)
+ : sock(sock),
+ state(Client::READING_REQUEST),
+ header_bytes_sent(0),
+ bytes_sent(0)
+{
+ request.reserve(1024);
+}
+
+Client::Client(const ClientProto &serialized)
+ : sock(serialized.sock()),
+ state(State(serialized.state())),
+ request(serialized.request()),
+ stream_id(serialized.stream_id()),
+ header(serialized.header()),
+ header_bytes_sent(serialized.header_bytes_sent()),
+ bytes_sent(serialized.bytes_sent())
+{
+}
+
+ClientProto Client::serialize() const
+{
+ ClientProto serialized;
+ serialized.set_sock(sock);
+ serialized.set_state(state);
+ serialized.set_request(request);
+ serialized.set_stream_id(stream_id);
+ serialized.set_header(header);
+ serialized.set_header_bytes_sent(serialized.header_bytes_sent());
+ serialized.set_bytes_sent(bytes_sent);
+ return serialized;
+}
+
Server::Server()
{
pthread_mutex_init(&mutex, NULL);
void Server::run()
{
- pthread_t thread;
- pthread_create(&thread, NULL, Server::do_work_thunk, this);
+ should_stop = false;
+
+ // Joinable is already the default, but it's good to be certain.
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&worker_thread, &attr, Server::do_work_thunk, this);
+}
+
+void Server::stop()
+{
+ {
+ MutexLock lock(&mutex);
+ should_stop = true;
+ }
+
+ if (pthread_join(worker_thread, NULL) == -1) {
+ perror("pthread_join");
+ exit(1);
+ }
}
void *Server::do_work_thunk(void *arg)
{
for ( ;; ) {
int nfds = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, EPOLL_TIMEOUT_MS);
-
- MutexLock lock(&mutex); // We release the mutex between iterations.
if (nfds == -1) {
perror("epoll_wait");
exit(1);
}
-
+
+ MutexLock lock(&mutex); // We release the mutex between iterations.
+
+ if (should_stop) {
+ return;
+ }
+
for (int i = 0; i < nfds; ++i) {
int fd = events[i].data.fd;
assert(clients.count(fd) != 0);
void Server::add_client(int sock)
{
MutexLock lock(&mutex);
- Client new_client;
- new_client.sock = sock;
- new_client.request.reserve(1024);
- new_client.state = Client::READING_REQUEST;
- new_client.header_bytes_sent = 0;
- new_client.bytes_sent = 0;
-
- clients.insert(make_pair(sock, new_client));
+ clients.insert(make_pair(sock, Client(sock)));
// Start listening on data from this socket.
epoll_event ev;