|
672 | 672 | """
|
673 | 673 | ConnectionOption(pq_opt::libpq_c.PQconninfoOption) -> ConnectionOption
|
674 | 674 |
|
675 |
| -Construct a `ConnectionOption` from a `libpg_c.PQconninfoOption`. |
| 675 | +Construct a `ConnectionOption` from a `libpq_c.PQconninfoOption`. |
676 | 676 | """
|
677 | 677 | function ConnectionOption(pq_opt::libpq_c.PQconninfoOption)
|
678 | 678 | return ConnectionOption(
|
@@ -789,3 +789,64 @@ function socket(conn::Ptr{libpq_c.PGconn})
|
789 | 789 | end
|
790 | 790 |
|
791 | 791 | socket(jl_conn::Connection) = socket(jl_conn.conn)
|
| 792 | + |
| 793 | +""" |
| 794 | +Sets the nonblocking connection status of the PG connections. |
| 795 | +While async_execute is non-blocking on the receiving side, |
| 796 | +the sending side is still nonblockign without this |
| 797 | +Returns true on success, false on failure |
| 798 | +
|
| 799 | +https://www.postgresql.org/docs/current/libpq-async.html |
| 800 | +""" |
| 801 | +function setnonblocking(jl_conn::Connection; nonblock=true) |
| 802 | + return libpq_c.PQsetnonblocking(jl_conn.conn, convert(Cint, nonblock)) == 0 |
| 803 | +end |
| 804 | + |
| 805 | +""" |
| 806 | +Checks whether the connection is non-blocking. |
| 807 | +Returns true if the connection is set to non-blocking, false otherwise |
| 808 | +
|
| 809 | +https://www.postgresql.org/docs/current/libpq-async.html |
| 810 | +""" |
| 811 | +function isnonblocking(jl_conn) |
| 812 | + return libpq_c.PQisnonblocking(jl_conn.conn) == 1 |
| 813 | +end |
| 814 | + |
| 815 | +""" |
| 816 | +Do the flush dance described in the libpq docs. Required when the |
| 817 | +connections are set to nonblocking and we want do send queries/data |
| 818 | +without blocking. |
| 819 | +
|
| 820 | +https://www.postgresql.org/docs/current/libpq-async.html#LIBPQ-PQFlush |
| 821 | +""" |
| 822 | +function flush(jl_conn) |
| 823 | + watcher = FDWatcher(socket(jl_conn), true, true) # can wait for reads and writes |
| 824 | + try |
| 825 | + while true # Iterators.repeated(true) # would make me more comfotable I think |
| 826 | + flushstatus = libpq_c.PQflush(jl_conn.conn) |
| 827 | + # 0 indicates success |
| 828 | + flushstatus == 0 && return true |
| 829 | + # -1 indicates error |
| 830 | + flushstatus < 0 && error(LOGGER, Errors.PQConnectionError(jl_conn)) |
| 831 | + # Could not send all data without blocking, need to wait FD |
| 832 | + flushstatus == 1 && begin |
| 833 | + wait(watcher) # Wait for the watcher |
| 834 | + # If it becomes write-ready, call PQflush again. |
| 835 | + if watcher.mask.writable |
| 836 | + continue # Call PGflush again, to send more data |
| 837 | + end |
| 838 | + if watcher.mask.readable |
| 839 | + # if the stream is readable, we have to consume data from the server first. |
| 840 | + success = libpq_c.PQconsumeInput(jl_conn.conn) == 1 |
| 841 | + !success && error(LOGGER, Errors.PQConnectionError(jl_conn)) |
| 842 | + end |
| 843 | + end |
| 844 | + end |
| 845 | + catch |
| 846 | + # We don't want to manage anything here |
| 847 | + rethrow() |
| 848 | + finally |
| 849 | + # Just close the watcher |
| 850 | + close(watcher) |
| 851 | + end |
| 852 | +end |
0 commit comments