Browse Source

H2O: Various small changes for round 15 (#2806)

The main additions are several extra checks for debug builds.
Also, now the application will set the CPU affinity mask if the
number of threads is a multiple of (as opposed to being equal to)
the number of logical processors.
Anton Kirilov 8 years ago
parent
commit
63b25d68fc

+ 2 - 0
frameworks/C/h2o/src/database.h

@@ -81,6 +81,8 @@ struct db_query_param_t {
 
 typedef struct {
 	list_t *db_conn;
+	// We use a FIFO queue instead of a simpler stack, otherwise the earlier queries may wait
+	// an unbounded amount of time to be executed.
 	queue_t queries;
 	size_t db_conn_num;
 	size_t free_db_conn_num;

+ 13 - 4
frameworks/C/h2o/src/fortune.c

@@ -18,6 +18,7 @@
 */
 
 #include <assert.h>
+#include <ctype.h>
 #include <h2o.h>
 #include <postgresql/libpq-fe.h>
 #include <stddef.h>
@@ -225,12 +226,20 @@ static result_return_t on_fortune_result(db_query_param_t *param, PGresult *resu
 			                                               sizeof(*fortune));
 
 			if (fortune) {
+				assert(PQnfields(result) == 2);
+
+				char * const id = PQgetvalue(result, i, 0);
+				char * const message = PQgetvalue(result, i, 1);
+				const size_t id_len = PQgetlength(result, i, 0);
+				const size_t message_len = PQgetlength(result, i, 1);
+
+				assert(id && id_len && isdigit(*id) && message);
 				memset(fortune, 0, sizeof(*fortune));
-				fortune->id.base = PQgetvalue(result, i, 0);
-				fortune->id.len = PQgetlength(result, i, 0);
+				fortune->id.base = id;
+				fortune->id.len = id_len;
 				fortune->message = h2o_htmlescape(&fortune_ctx->req->pool,
-				                                  PQgetvalue(result, i, 1),
-				                                  PQgetlength(result, i, 1));
+				                                  message,
+				                                  message_len);
 				fortune->l.next = fortune_ctx->result;
 				fortune_ctx->result = &fortune->l;
 				fortune_ctx->num_result++;

+ 7 - 1
frameworks/C/h2o/src/request_handler.c

@@ -47,11 +47,17 @@ static int json_serializer(struct st_h2o_handler_t *self, h2o_req_t *req)
 	                                                      req->conn->ctx);
 	json_generator_t * const gen = get_json_generator(&ctx->json_generator,
 	                                                  &ctx->json_generator_num);
+	const struct {
+		const char *message;
+	} object = {HELLO_RESPONSE};
 
 	if (gen) {
 		CHECK_YAJL_STATUS(yajl_gen_map_open, gen->gen);
 		CHECK_YAJL_STATUS(yajl_gen_string, gen->gen, YAJL_STRLIT("message"));
-		CHECK_YAJL_STATUS(yajl_gen_string, gen->gen, YAJL_STRLIT(HELLO_RESPONSE));
+		CHECK_YAJL_STATUS(yajl_gen_string,
+		                  gen->gen,
+		                  (const unsigned char *) object.message,
+		                  strlen(object.message));
 		CHECK_YAJL_STATUS(yajl_gen_map_close, gen->gen);
 
 		// The response is small enough, so that it is simpler to copy it

+ 5 - 5
frameworks/C/h2o/src/thread.c

@@ -115,18 +115,18 @@ void start_threads(global_thread_data_t *global_thread_data)
 	// The first thread context is used by the main thread.
 	global_thread_data->thread = pthread_self();
 
-	// If the number of threads is not equal to the number of processors, then let the scheduler
-	// decide how to balance the load.
-	if (global_thread_data->config->thread_num == num_cpus) {
+	// If the number of threads is not a multiple of the number of processors, then
+	// let the scheduler decide how to balance the load.
+	if (global_thread_data->config->thread_num % num_cpus == 0) {
 		CPU_ZERO_S(cpusetsize, cpuset);
 		CPU_SET_S(0, cpusetsize, cpuset);
 		CHECK_ERROR(pthread_setaffinity_np, global_thread_data->thread, cpusetsize, cpuset);
 	}
 
 	for (size_t i = global_thread_data->config->thread_num - 1; i > 0; i--) {
-		if (global_thread_data->config->thread_num == num_cpus) {
+		if (global_thread_data->config->thread_num % num_cpus == 0) {
 			CPU_ZERO_S(cpusetsize, cpuset);
-			CPU_SET_S(i, cpusetsize, cpuset);
+			CPU_SET_S(i % num_cpus, cpusetsize, cpuset);
 			CHECK_ERROR(pthread_attr_setaffinity_np, &attr, cpusetsize, cpuset);
 		}
 

+ 19 - 5
frameworks/C/h2o/src/world.c

@@ -18,6 +18,7 @@
 */
 
 #include <assert.h>
+#include <ctype.h>
 #include <h2o.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -408,8 +409,11 @@ static result_return_t on_single_query_result(db_query_param_t *param, PGresult
 		assert(PQntuples(result) == 1);
 		assert(PQgetlength(result, 0, 1) == sizeof(random_number));
 
+		const void * const r = PQgetvalue(result, 0, 1);
+
+		assert(r);
 		// Use memcpy() in case the result is not aligned.
-		memcpy(&random_number, PQgetvalue(result, 0, 1), sizeof(random_number));
+		memcpy(&random_number, r, sizeof(random_number));
 		random_number = ntohl(random_number);
 		PQclear(result);
 
@@ -484,25 +488,35 @@ static void process_result(PGresult *result, query_result_t *out)
 
 	const char * const id = PQgetvalue(result, 0, 0);
 	const char * const random_number = PQgetvalue(result, 0, 1);
+	const size_t id_len = PQgetlength(result, 0, 0);
+	const size_t random_number_len = PQgetlength(result, 0, 1);
+
+	assert(id && id_len && random_number && random_number_len);
 
 	if (PQfformat(result, 0)) {
-		assert(PQgetlength(result, 0, 0) == sizeof(out->id));
+		assert(id_len == sizeof(out->id));
 		// Use memcpy() in case the result is not aligned; the reason we are
 		// copying over the id is because the results may arrive in any order.
 		memcpy(&out->id, id, sizeof(out->id));
 		out->id = ntohl(out->id);
 	}
-	else
+	else {
+		assert(isdigit(*id));
 		out->id = atoi(id);
+	}
+
+	assert(out->id <= MAX_ID);
 
 	if (PQfformat(result, 1)) {
-		assert(PQgetlength(result, 0, 1) == sizeof(out->random_number));
+		assert(random_number_len == sizeof(out->random_number));
 		// Use memcpy() in case the result is not aligned.
 		memcpy(&out->random_number, random_number, sizeof(out->random_number));
 		out->random_number = ntohl(out->random_number);
 	}
-	else
+	else {
+		assert(isdigit(*random_number));
 		out->random_number = atoi(random_number);
+	}
 }
 
 static int serialize_item(uint32_t id, uint32_t random_number, yajl_gen gen)