[mw-devel] [Git][arthur/mw][master] Defer closing replay files

Andrew Price welshbyte at sucs.org
Sun Nov 26 12:28:28 GMT 2017


Andrew Price pushed to branch master at Justin Mitchell / mw


Commits:
d6b35f9f by Andrew Price at 2017-11-26T11:49:48+00:00
Defer closing replay files

close()ing replay files after storing a message can block on i/o under
certain conditions. Stuff the fds of the opened files into a list and
process that list only when a poll_wait() times out, which means there
are no messages waiting to be processed. Under flood conditions where
the list is full of open fds, they'll be reused when storing new
messages.

- - - - -


3 changed files:

- src/server/replay.c
- src/server/replay.h
- src/server/servsock.c


Changes:

=====================================
src/server/replay.c
=====================================
--- a/src/server/replay.c
+++ b/src/server/replay.c
@@ -47,14 +47,43 @@ static int store_wrap(int index)
 	return index;
 }
 
+static int replay_fds[STORE_SIZE];
+
+void replay_commit(void)
+{
+	/* If a user pastes a novel into the talker we don't want to be stuck
+	   doing i/o for a long time afterwards, so a rate limit is needed. */
+#define COMMIT_RATELIMIT (10)
+	static unsigned i = 0;
+	unsigned closed = 0;
+
+	for (; i < STORE_SIZE && closed < COMMIT_RATELIMIT; i++) {
+		int fd = replay_fds[i];
+		if (fd >= 0) {
+			replay_fds[i] = -1;
+			fsync(fd);
+			close(fd);
+			closed++;
+		}
+	}
+	if (i == STORE_SIZE)
+		i = 0;
+}
+
+static void defer_close(unsigned n, int fd)
+{
+	replay_fds[n] = fd;
+}
+
 static int write_message(ipc_message_t *msg, unsigned n)
 {
 	char pathname[STORE_FILE_NAME_LEN];
+	int fd = replay_fds[n];
 	struct iovec iov[2];
-	int fd;
 
 	sprintf(pathname, REPLAY_DIR "/%0*u", (int)STORE_SIZE_LEN, n);
-	fd = open(pathname, O_RDWR|O_CLOEXEC|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
+	if (fd < 0)
+		fd = open(pathname, O_RDWR|O_CLOEXEC|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
 	if (fd < 0) {
 		perror(pathname);
 		return 1;
@@ -69,7 +98,7 @@ static int write_message(ipc_message_t *msg, unsigned n)
 	};
 	if (pwritev(fd, iov, 2, 0) != (iov[0].iov_len + iov[1].iov_len))
 		perror(pathname);
-	close(fd);
+	defer_close(n, fd);
 	return 0;
 }
 
@@ -255,6 +284,7 @@ int replay_init(void)
 		struct stat st;
 		int fd;
 
+		replay_fds[i] = -1;
 		sprintf(pathname, REPLAY_DIR "/%0*u", (int)STORE_SIZE_LEN, i);
 		fd = open(pathname, O_RDONLY|O_CLOEXEC|O_CREAT, S_IRUSR|S_IWUSR);
 		if (fd < 0) {


=====================================
src/server/replay.h
=====================================
--- a/src/server/replay.h
+++ b/src/server/replay.h
@@ -5,5 +5,6 @@ int replay_init(void);
 void store_message(ipc_message_t *msg);
 void assign_serial(ipc_message_t *msg);
 void replay(ipc_connection_t *conn, ipc_message_t *msg);
+void replay_commit(void);
 
 #endif /* REPLAY_H */


=====================================
src/server/servsock.c
=====================================
--- a/src/server/servsock.c
+++ b/src/server/servsock.c
@@ -143,7 +143,7 @@ static int mainsock_event_cb(poll_event_t *events, int nmemb, void *data)
 		/* event on mainsock */
 		if (ev->data == NULL) {
 			if (ev->is_error) {
-				return 1;
+				return -1;
 			} else
 			if (ev->is_read) {
 				accept_connection(*mainsock);
@@ -182,7 +182,7 @@ static int mainsock_event_cb(poll_event_t *events, int nmemb, void *data)
 			}
 		}
 	}
-	return 0;
+	return nmemb;
 }
 
 void watch_mainsock(int mainsock)
@@ -199,6 +199,8 @@ void watch_mainsock(int mainsock)
 	do {
 		while ((ret = poll_wait(1000, mainsock_event_cb, &mainsock)) >= 0) {
 			/* end of events handling, do periodic stuff here */
+			if (ret == 0)
+				replay_commit();
 		}
 		/* poll got interrupted, not actually an error, go around again */
 	} while (ret == -1 && errno == EINTR);



View it on GitLab: https://projects.sucs.org/arthur/mw/commit/d6b35f9f9dedf155060e4d8d308eae92a9e01381

---
View it on GitLab: https://projects.sucs.org/arthur/mw/commit/d6b35f9f9dedf155060e4d8d308eae92a9e01381
You're receiving this email because of your account on projects.sucs.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sucs.org/pipermail/mw-devel/attachments/20171126/f50008a5/attachment-0001.html>


More information about the mw-devel mailing list