Răsfoiți Sursa

H2O: Various changes (#3577)

* Make a further adjustment to the number of database connections.
* Fix a use of deallocated memory in some database error code paths.
* Clean up the Dockerfiles and scripts - in particular, Ruby is no
longer required by the C implementation, which should reduce the
build time.
* Update mustache-c to revision 01f1e47.
Anton Kirilov 7 ani în urmă
părinte
comite
47ec0bfe8f

+ 24 - 32
frameworks/C/h2o/h2o.dockerfile

@@ -1,56 +1,48 @@
-FROM ruby:2.4
+FROM ubuntu:16.04
 
 COPY ./ ./
 
-RUN apt update
-RUN apt install -yqq cmake automake libpq-dev libnuma-dev checkinstall autoconf pkg-config \
-    libtool python-sphinx libcunit1-dev nettle-dev libyaml-dev bison
+RUN apt update && \
+    apt install -yqq autoconf bison cmake curl file flex g++ git libnuma-dev libpq-dev libssl-dev \
+                     libtool make wget
 
 ### Install mustache-c
 
+ENV MUSTACHE_C_HOME=/mustache-c
+
 RUN git clone https://github.com/x86-64/mustache-c.git && \
     cd mustache-c && \
-    git checkout 55dafd1e95adaca90ea50efb9a8573786514c85a && \
-    CFLAGS="-O3 -flto -march=native" ./configure --prefix=/mustache-c && \
+    git checkout 01f1e4732c4862071bbf07242128abf1e28cc105 && \
+    CFLAGS="-O3 -flto -march=native" ./autogen.sh --prefix="$MUSTACHE_C_HOME" && \
     make -j "$(nproc)" install
 
-ENV MUSTACHE_C_HOME=/mustache-c
-ENV LD_LIBRARY_PATH=/mustache-c/lib:${LD_LIBRARY_PATH}
+ENV LD_LIBRARY_PATH="${MUSTACHE_C_HOME}/lib:$LD_LIBRARY_PATH"
 
 ### Install yajl
 
-ENV YAJL_VERSION="2.1.0"
+ENV YAJL_VERSION=2.1.0
 ENV YAJL_ARCHIVE="${YAJL_VERSION}.tar.gz"
-ENV YAJL_BUILD_DIR="yajl-${YAJL_VERSION}"
+ENV YAJL_HOME=/yajl
 
-RUN wget -q https://github.com/lloyd/yajl/archive/${YAJL_ARCHIVE} && \
-    tar xf ${YAJL_ARCHIVE} && \
-    cd ${YAJL_BUILD_DIR} && \
-    ./configure -p /yajl && \
+RUN wget -q "https://github.com/lloyd/yajl/archive/$YAJL_ARCHIVE" && \
+    tar xf "$YAJL_ARCHIVE" && \
+    cd "yajl-$YAJL_VERSION" && \
+    ./configure -p "$YAJL_HOME" && \
     make -j "$(nproc)" install
 
-ENV YAJL_HOME=/yajl
-ENV LD_LIBRARY_PATH=/yajl/lib:${LD_LIBRARY_PATH}
+ENV LD_LIBRARY_PATH="${YAJL_HOME}/lib:$LD_LIBRARY_PATH"
 
 ### Install h2o
 
-ENV IROOT="/install"
-ENV H2O_HOME="${IROOT}/h2o"
-ENV VERSION="2.2.4"
-ENV ARCHIVE="v${VERSION}.tar.gz"
-ENV BUILD_DIR="h2o-${VERSION}"
-
-RUN mkdir install
-RUN cd "${IROOT}" && \
-    wget -q "https://github.com/h2o/h2o/archive/$ARCHIVE" && \
-    tar xf "$ARCHIVE" && \
-    cd "$BUILD_DIR" && \
+ENV H2O_VERSION=2.2.4
+ENV H2O_ARCHIVE="v${H2O_VERSION}.tar.gz"
+ENV H2O_HOME=/h2o
+
+RUN wget -q "https://github.com/h2o/h2o/archive/$H2O_ARCHIVE" && \
+    tar xf "$H2O_ARCHIVE" && \
+    cd "h2o-$H2O_VERSION" && \
     cmake -DCMAKE_INSTALL_PREFIX="$H2O_HOME" -DCMAKE_C_FLAGS="-flto -march=native" \
-      -DCMAKE_AR=/usr/bin/gcc-ar -DCMAKE_RANLIB=/usr/bin/gcc-ranlib -DWITH_MRUBY=on && \
+          -DCMAKE_AR=/usr/bin/gcc-ar -DCMAKE_RANLIB=/usr/bin/gcc-ranlib && \
     make -j "$(nproc)" install
 
-ENV PATH=${H2O_HOME}/bin:${PATH}
-
-RUN chmod a+wrx start-servers.sh
-
 CMD ["./start-servers.sh"]

+ 35 - 13
frameworks/C/h2o/src/database.c

@@ -45,7 +45,7 @@ typedef struct {
 } db_conn_t;
 
 static int do_database_write(db_conn_t *db_conn);
-static void do_execute_query(db_conn_t *db_conn);
+static int do_execute_query(db_conn_t *db_conn, bool direct_notification);
 static void error_notification(thread_context_t *ctx, bool timeout, const char *error_string);
 static void on_database_connect_error(db_conn_t *db_conn, bool timeout, const char *error_string);
 static void on_database_connect_timeout(h2o_timeout_entry_t *entry);
@@ -85,7 +85,7 @@ static int do_database_write(db_conn_t *db_conn)
 	return ret;
 }
 
-static void do_execute_query(db_conn_t *db_conn)
+static int do_execute_query(db_conn_t *db_conn, bool direct_notification)
 {
 	const int ec = db_conn->param->flags & IS_PREPARED ?
 	               PQsendQueryPrepared(db_conn->conn,
@@ -96,6 +96,7 @@ static void do_execute_query(db_conn_t *db_conn)
 	                                   db_conn->param->paramFormats,
 	                                   db_conn->param->resultFormat) :
 	               PQsendQuery(db_conn->conn, db_conn->param->command);
+	int ret = EXIT_FAILURE;
 
 	if (ec) {
 		if (db_conn->param->flags & IS_SINGLE_ROW)
@@ -106,12 +107,32 @@ static void do_execute_query(db_conn_t *db_conn)
 		                 &db_conn->ctx->db_state.h2o_timeout,
 		                 &db_conn->h2o_timeout_entry);
 		h2o_socket_read_start(db_conn->sock, on_database_read_ready);
-		on_database_write_ready(db_conn->sock, NULL);
+
+		const int send_status = PQflush(db_conn->conn);
+
+		if (send_status < 0) {
+			if (direct_notification)
+				db_conn->param = NULL;
+
+			LIBRARY_ERROR("PQflush", PQerrorMessage(db_conn->conn));
+			on_database_error(db_conn, DB_ERROR);
+		}
+		else {
+			ret = EXIT_SUCCESS;
+
+			if (send_status)
+				h2o_socket_notify_write(db_conn->sock, on_database_write_ready);
+		}
 	}
 	else {
+		if (direct_notification)
+			db_conn->param = NULL;
+
 		ERROR(PQerrorMessage(db_conn->conn));
 		on_database_error(db_conn, DB_ERROR);
 	}
+
+	return ret;
 }
 
 static void error_notification(thread_context_t *ctx, bool timeout, const char *error_string)
@@ -348,7 +369,7 @@ static void process_query(db_conn_t *db_conn)
 		                                        l,
 		                                        db_conn->ctx->db_state.queries.head);
 		db_conn->ctx->db_state.queries.head = db_conn->ctx->db_state.queries.head->next;
-		do_execute_query(db_conn);
+		do_execute_query(db_conn, false);
 	}
 	else {
 		db_conn->l.next = db_conn->ctx->db_state.db_conn;
@@ -446,7 +467,7 @@ void connect_to_database(thread_context_t *ctx)
 
 int execute_query(thread_context_t *ctx, db_query_param_t *param)
 {
-	int ret = EXIT_SUCCESS;
+	int ret = EXIT_FAILURE;
 
 	if (ctx->db_state.free_db_conn_num) {
 		db_conn_t * const db_conn = H2O_STRUCT_FROM_MEMBER(db_conn_t, l, ctx->db_state.db_conn);
@@ -454,19 +475,20 @@ int execute_query(thread_context_t *ctx, db_query_param_t *param)
 		ctx->db_state.db_conn = db_conn->l.next;
 		ctx->db_state.free_db_conn_num--;
 		db_conn->param = param;
-		do_execute_query(db_conn);
+		ret = do_execute_query(db_conn, true);
 	}
 	else if (ctx->db_state.query_num < ctx->config->max_query_num) {
-		param->l.next = NULL;
-		*ctx->db_state.queries.tail = &param->l;
-		ctx->db_state.queries.tail = &param->l.next;
-		ctx->db_state.query_num++;
-
 		if (ctx->db_state.db_conn_num < ctx->config->max_db_conn_num)
 			start_database_connect(ctx, NULL);
+
+		if (ctx->db_state.db_conn_num) {
+			param->l.next = NULL;
+			*ctx->db_state.queries.tail = &param->l;
+			ctx->db_state.queries.tail = &param->l.next;
+			ctx->db_state.query_num++;
+			ret = EXIT_SUCCESS;
+		}
 	}
-	else
-		ret = EXIT_FAILURE;
 
 	return ret;
 }

+ 17 - 14
frameworks/C/h2o/start-servers.sh

@@ -1,12 +1,14 @@
 #!/bin/bash
 
-TROOT="/"
-H2O_APP_HOME="${IROOT}/h2o_app"
-BUILD_DIR="${H2O_APP_HOME}_build"
+set -e
+
+CPU_COUNT="$(nproc)"
+H2O_APP_HOME=/h2o_app
+H2O_APP_BUILD_DIR="${H2O_APP_HOME}_build"
 H2O_APP_PROFILE_PORT=54321
 H2O_APP_PROFILE_URL="http://127.0.0.1:$H2O_APP_PROFILE_PORT"
-NUM_WORKERS=$(nproc)
-CPU_COUNT=$(nproc)
+NUM_WORKERS="$CPU_COUNT"
+TROOT=/
 
 # A hacky way to detect whether we are running in the physical hardware or the cloud environment.
 if [[ "$CPU_COUNT" -gt 16 ]]; then
@@ -14,7 +16,7 @@ if [[ "$CPU_COUNT" -gt 16 ]]; then
 	# In the physical hardware environment the number of threads used by the application is not
 	# the same as the number of logical CPU cores that the database server has, so we need to
 	# adjust the maximum number of database connections per thread accordingly.
-	DB_CONN=2
+	DB_CONN=4
 else
 	USE_PROCESSES=false
 	DB_CONN=8
@@ -38,14 +40,15 @@ run_curl()
 run_h2o_app()
 {
 	taskset -c "$1" "$2/h2o_app" -a20 -f "$3/template/fortunes.mustache" -m "$DB_CONN" "$4" "$5" \
-		-d "host=tfb-database dbname=hello_world user=benchmarkdbuser password=benchmarkdbpass" &
+	        -d "host=tfb-database dbname=hello_world user=benchmarkdbuser \
+	            password=benchmarkdbpass" &
 }
 
 generate_profile_data()
 {
-	run_h2o_app 0 . "${TROOT}" -p$H2O_APP_PROFILE_PORT -t1
+	run_h2o_app 0 . "$TROOT" "-p$H2O_APP_PROFILE_PORT" -t1
 	local -r H2O_APP_PROFILE_PID=$!
-	while ! curl ${H2O_APP_PROFILE_URL} > /dev/null 2>&1; do sleep 1; done
+	while ! curl "$H2O_APP_PROFILE_URL" > /dev/null 2>&1; do sleep 1; done
 	run_curl json
 	run_curl db
 	run_curl queries?queries=20
@@ -53,12 +56,12 @@ generate_profile_data()
 	run_curl updates?queries=20
 	run_curl plaintext
 	run_curl cached-worlds?queries=20
-	kill -s SIGTERM $H2O_APP_PROFILE_PID
-	wait $H2O_APP_PROFILE_PID
+	kill -s SIGTERM "$H2O_APP_PROFILE_PID"
+	wait "$H2O_APP_PROFILE_PID"
 }
 
-install -d "$BUILD_DIR"
-pushd "$BUILD_DIR"
+install -d "$H2O_APP_BUILD_DIR"
+pushd "$H2O_APP_BUILD_DIR"
 build_h2o_app "-fprofile-generate"
 generate_profile_data
 make clean
@@ -66,7 +69,7 @@ rm -f CMakeCache.txt
 build_h2o_app "-fprofile-use"
 make -j "$CPU_COUNT" install
 popd
-rm -rf "$BUILD_DIR"
+rm -rf "$H2O_APP_BUILD_DIR"
 echo "Maximum database connections per thread: $DB_CONN"
 
 if "$USE_PROCESSES"; then

+ 12 - 20
frameworks/Ruby/h2o_mruby/h2o_mruby.dockerfile

@@ -1,26 +1,18 @@
 FROM ruby:2.4
 
-ENV H2O_HOME=/h2o
-ENV VERSION="2.2.4"
-ENV ARCHIVE=v${VERSION}.tar.gz
-ENV BUILD_DIR=h2o-${VERSION}
-
-RUN mkdir /h2o
-
-WORKDIR /h2o
+ADD ./h2o.conf ./
 
-RUN wget -q https://github.com/h2o/h2o/archive/$ARCHIVE
-RUN tar xf $ARCHIVE
+RUN apt update && apt install -yqq bison cmake libssl-dev make
 
-WORKDIR /h2o/h2o-2.2.4
-
-RUN apt update -yqq && apt install -yqq make cmake libmcrypt-dev libssl-dev bison
-RUN cmake -DCMAKE_INSTALL_PREFIX="$H2O_HOME" -DCMAKE_C_FLAGS="-flto -march=native" \
-      -DCMAKE_AR=/usr/bin/gcc-ar -DCMAKE_RANLIB=/usr/bin/gcc-ranlib -DWITH_MRUBY=on
-RUN make -j "$(nproc)" install
-
-ENV PATH=/h2o/bin:${PATH}
+ENV H2O_VERSION=2.2.4
+ENV H2O_ARCHIVE="v${H2O_VERSION}.tar.gz"
+ENV H2O_HOME=/h2o
 
-ADD ./h2o.conf /h2o_mruby/
+RUN wget -q "https://github.com/h2o/h2o/archive/$H2O_ARCHIVE" && \
+    tar xf "$H2O_ARCHIVE" && \
+    cd "h2o-$H2O_VERSION" && \
+    cmake -DCMAKE_INSTALL_PREFIX="$H2O_HOME" -DCMAKE_C_FLAGS="-flto -march=native" \
+          -DCMAKE_AR=/usr/bin/gcc-ar -DCMAKE_RANLIB=/usr/bin/gcc-ranlib -DWITH_MRUBY=on && \
+    make -j "$(nproc)" install
 
-CMD "${H2O_HOME}/bin/h2o" -c "/h2o_mruby/h2o.conf"
+CMD "${H2O_HOME}/bin/h2o" -c h2o.conf