]> granicus.if.org Git - pgbouncer/commitdiff
sbuf: improved sbuf_loopcnt logic
authorMarko Kreen <markokr@gmail.com>
Fri, 4 Dec 2015 10:14:03 +0000 (12:14 +0200)
committerMarko Kreen <markokr@gmail.com>
Fri, 4 Dec 2015 12:44:47 +0000 (14:44 +0200)
Simple early exit won't work for TLS as all data
may be in libssl buffers and no network wakeup is coming.

Use special-case event_add() with timeout for postponing.

It might be even improve non-tls case as there could
be specific buffers lengths when even that does
postponing while nothing is coming from network.

src/sbuf.c

index b651717e426ec4a12e33cba23eef9311a21be36f..5c89ffec0343c5f2dfc2132e4783d1a1e590f8c6 100644 (file)
@@ -409,6 +409,42 @@ static bool sbuf_wait_for_data(SBuf *sbuf)
        return true;
 }
 
+static void sbuf_recv_forced_cb(int sock, short flags, void *arg)
+{
+       SBuf *sbuf = arg;
+
+       sbuf->wait_type = W_NONE;
+
+       if (sbuf_wait_for_data(sbuf)) {
+               sbuf_recv_cb(sock, flags, arg);
+       } else {
+               sbuf_call_proto(sbuf, SBUF_EV_RECV_FAILED);
+       }
+}
+
+static bool sbuf_wait_for_data_forced(SBuf *sbuf)
+{
+       int err;
+       struct timeval tv_min;
+
+       tv_min.tv_sec = 0;
+       tv_min.tv_usec = 1;
+
+       if (sbuf->wait_type != W_NONE) {
+               event_del(&sbuf->ev);
+               sbuf->wait_type = W_NONE;
+       }
+
+       event_set(&sbuf->ev, sbuf->sock, EV_READ, sbuf_recv_forced_cb, sbuf);
+       err = event_add(&sbuf->ev, &tv_min);
+       if (err < 0) {
+               log_warning("sbuf_wait_for_data: event_add failed: %s", strerror(errno));
+               return false;
+       }
+       sbuf->wait_type = W_ONCE;
+       return true;
+}
+
 /* libevent EV_WRITE: called when dest socket is writable again */
 static void sbuf_send_cb(int sock, short flags, void *arg)
 {
@@ -686,6 +722,8 @@ try_more:
                 * after resync to process all data. (result is ignored)
                 */
                ok = sbuf_process_pending(sbuf);
+
+               sbuf_wait_for_data_forced(sbuf);
                return;
        }
        loopcnt++;