diff --git a/web/pgadmin/utils/driver/abstract.py b/web/pgadmin/utils/driver/abstract.py index 1722e21fc..32e1c976f 100644 --- a/web/pgadmin/utils/driver/abstract.py +++ b/web/pgadmin/utils/driver/abstract.py @@ -168,7 +168,6 @@ class BaseConnection(object): ASYNC_WRITE_TIMEOUT = 3 ASYNC_NOT_CONNECTED = 4 ASYNC_EXECUTION_ABORTED = 5 - ASYNC_TIMEOUT = 0.2 @abstractmethod def connect(self, **kwargs): diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py b/web/pgadmin/utils/driver/psycopg2/__init__.py index a41215303..81442e498 100644 --- a/web/pgadmin/utils/driver/psycopg2/__init__.py +++ b/web/pgadmin/utils/driver/psycopg2/__init__.py @@ -110,7 +110,7 @@ class Connection(BaseConnection): - This method is used to wait for asynchronous connection. This is a blocking call. - * _wait_timeout(conn) + * _wait_timeout(conn, time) - This method is used to wait for asynchronous connection with timeout. This is a non blocking call. @@ -1261,27 +1261,51 @@ Failed to reset the connection to the server due to following error: Args: conn: connection object + time: wait time """ - while 1: + + state = conn.poll() + if state == psycopg2.extensions.POLL_OK: + return self.ASYNC_OK + elif state == psycopg2.extensions.POLL_WRITE: + # Wait for the given time and then check the return status + # If three empty lists are returned then the time-out is reached. + timeout_status = select.select([], [conn.fileno()], [], 0) + if timeout_status == ([], [], []): + return self.ASYNC_WRITE_TIMEOUT + + # poll again to check the state if it is still POLL_WRITE + # then return ASYNC_WRITE_TIMEOUT else return ASYNC_OK. state = conn.poll() - if state == psycopg2.extensions.POLL_OK: - return self.ASYNC_OK - elif state == psycopg2.extensions.POLL_WRITE: - # Wait for the given time and then check the return status - # If three empty lists are returned then the time-out is reached. - timeout_status = select.select([], [conn.fileno()], [], self.ASYNC_TIMEOUT) - if timeout_status == ([], [], []): - return self.ASYNC_WRITE_TIMEOUT - elif state == psycopg2.extensions.POLL_READ: - # Wait for the given time and then check the return status - # If three empty lists are returned then the time-out is reached. - timeout_status = select.select([conn.fileno()], [], [], self.ASYNC_TIMEOUT) - if timeout_status == ([], [], []): - return self.ASYNC_READ_TIMEOUT - else: - raise psycopg2.OperationalError( - "poll() returned %s from _wait_timeout function" % state - ) + if state == psycopg2.extensions.POLL_WRITE: + return self.ASYNC_WRITE_TIMEOUT + return self.ASYNC_OK + elif state == psycopg2.extensions.POLL_READ: + # Wait for the given time and then check the return status + # If three empty lists are returned then the time-out is reached. + timeout_status = select.select([conn.fileno()], [], [], 0) + if timeout_status == ([], [], []): + return self.ASYNC_READ_TIMEOUT + + # select.select timeout option works only if we provide + # empty [] [] [] file descriptor in select.select() function + # and that also works only on UNIX based system, it do not support + # Windows Hence we have wrote our own pooling mechanism to read + # data fast each call conn.poll() reads chunks of data from + # connection object more we poll more we read data from connection + cnt = 0 + while cnt < 1000: + # poll again to check the state if it is still POLL_READ + # then return ASYNC_READ_TIMEOUT else return ASYNC_OK. + state = conn.poll() + if state == psycopg2.extensions.POLL_OK: + return self.ASYNC_OK + cnt += 1 + return self.ASYNC_READ_TIMEOUT + else: + raise psycopg2.OperationalError( + "poll() returned %s from _wait_timeout function" % state + ) def poll(self, formatted_exception_msg=False, no_result=False): """