mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-10-30 23:37:29 +03:00 
			
		
		
		
	Added wait callback and functions to deal with it.
This commit is contained in:
		
							parent
							
								
									02a28ff028
								
							
						
					
					
						commit
						1446f046e9
					
				|  | @ -60,6 +60,11 @@ from _psycopg import ISQLQuote | |||
| 
 | ||||
| from _psycopg import QueryCanceledError, TransactionRollbackError | ||||
| 
 | ||||
| try: | ||||
|     from _psycopg import set_wait_callback | ||||
| except ImportError: | ||||
|     pass | ||||
| 
 | ||||
| """Isolation level values.""" | ||||
| ISOLATION_LEVEL_AUTOCOMMIT     = 0 | ||||
| ISOLATION_LEVEL_READ_COMMITTED = 1  | ||||
|  | @ -83,6 +88,7 @@ STATUS_IN_TRANSACTION = STATUS_BEGIN | |||
| POLL_OK    = 0 | ||||
| POLL_READ  = 1 | ||||
| POLL_WRITE = 2 | ||||
| POLL_ERROR = 3 | ||||
| 
 | ||||
| """Backend transaction status values.""" | ||||
| TRANSACTION_STATUS_IDLE    = 0 | ||||
|  |  | |||
|  | @ -484,4 +484,28 @@ def register_tstz_w_secs(oids=None, conn_or_curs=None): | |||
|     return _ext.TSTZ_W_SECS | ||||
| 
 | ||||
| 
 | ||||
| import select | ||||
| from psycopg2.extensions import POLL_OK, POLL_READ, POLL_WRITE | ||||
| from psycopg2 import OperationalError | ||||
| 
 | ||||
| def wait_select(conn, curs=None): | ||||
|     """Wait until a connection or cursor has data available. | ||||
| 
 | ||||
|     The function is an example of a wait callback to be registered with | ||||
|     `~psycopg2.extensions.set_wait_callback()`. This function uses `!select()` | ||||
|     to wait for data available. | ||||
|     """ | ||||
|     poll = (curs or conn).poll | ||||
|     while 1: | ||||
|         state = poll() | ||||
|         if state == POLL_OK: | ||||
|             break | ||||
|         elif state == POLL_READ: | ||||
|             select.select([conn.fileno()], [], []) | ||||
|         elif state == POLL_WRITE: | ||||
|             select.select([], [conn.fileno()], []) | ||||
|         else: | ||||
|             raise OperationalError("bad state from poll: %s" % state) | ||||
| 
 | ||||
| 
 | ||||
| __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) | ||||
|  |  | |||
							
								
								
									
										94
									
								
								psycopg/green.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								psycopg/green.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | |||
| /* green.c - cooperation with coroutine libraries.
 | ||||
|  * | ||||
|  * Copyright (C) 2010 Daniele Varrazzo <daniele.varrazzo@gmail.com> | ||||
|  * | ||||
|  * This file is part of psycopg. | ||||
|  * | ||||
|  * psycopg2 is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * In addition, as a special exception, the copyright holders give | ||||
|  * permission to link this program with the OpenSSL library (or with | ||||
|  * modified versions of OpenSSL that use the same license as OpenSSL), | ||||
|  * and distribute linked combinations including the two. | ||||
|  * | ||||
|  * You must obey the GNU Lesser General Public License in all respects for | ||||
|  * all of the code used other than OpenSSL. | ||||
|  * | ||||
|  * psycopg2 is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public | ||||
|  * License for more details. | ||||
|  */ | ||||
| 
 | ||||
| #define PSYCOPG_MODULE | ||||
| #include "psycopg/config.h" | ||||
| #include "psycopg/python.h" | ||||
| #include "psycopg/psycopg.h" | ||||
| #include "psycopg/green.h" | ||||
| 
 | ||||
| HIDDEN PyObject *wait_callback = NULL; | ||||
| 
 | ||||
| /* Register a callback function to block waiting for data.
 | ||||
|  * | ||||
|  * The function is exported by the _psycopg module. | ||||
|  */ | ||||
| PyObject * | ||||
| psyco_set_wait_callback(PyObject *self, PyObject *obj) | ||||
| { | ||||
|     Py_XDECREF(wait_callback); | ||||
| 
 | ||||
|     if (obj != Py_None) { | ||||
|         wait_callback = obj; | ||||
|         Py_INCREF(obj); | ||||
|     } | ||||
|     else { | ||||
|         wait_callback = NULL; | ||||
|     } | ||||
| 
 | ||||
|     Py_INCREF(Py_None); | ||||
|     return Py_None; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Return nonzero if a wait callback should be called. */ | ||||
| int | ||||
| psyco_green() | ||||
| { | ||||
| #ifdef PSYCOPG_EXTENSIONS | ||||
|     return (NULL != wait_callback); | ||||
| #else | ||||
|     return 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /* Block waiting for data available in an async connection.
 | ||||
|  * | ||||
|  * This function assumes `wait_callback` to be available: | ||||
|  * raise `InterfaceError` if it is not. Use `psyco_green()` to check if | ||||
|  * the function is to be called. | ||||
|  * | ||||
|  * The function returns the return value of the called function. | ||||
|  */ | ||||
| PyObject * | ||||
| psyco_wait(PyObject *conn, PyObject *curs) | ||||
| { | ||||
|     PyObject *rv; | ||||
|     PyObject *cb; | ||||
| 
 | ||||
|     Dprintf("psyco_wait"); | ||||
|     cb = wait_callback; | ||||
|     if (!cb) { | ||||
|         PyErr_SetString(OperationalError, "wait callback not available"); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     Py_INCREF(cb); | ||||
|     rv = PyObject_CallFunctionObjArgs(cb, conn, curs, NULL); | ||||
|     Py_DECREF(cb); | ||||
| 
 | ||||
|     return rv; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										58
									
								
								psycopg/green.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								psycopg/green.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| /* green.c - cooperation with coroutine libraries.
 | ||||
|  * | ||||
|  * Copyright (C) 2010 Daniele Varrazzo <daniele.varrazzo@gmail.com> | ||||
|  * | ||||
|  * This file is part of psycopg. | ||||
|  * | ||||
|  * psycopg2 is free software: you can redistribute it and/or modify it | ||||
|  * under the terms of the GNU Lesser General Public License as published | ||||
|  * by the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * In addition, as a special exception, the copyright holders give | ||||
|  * permission to link this program with the OpenSSL library (or with | ||||
|  * modified versions of OpenSSL that use the same license as OpenSSL), | ||||
|  * and distribute linked combinations including the two. | ||||
|  * | ||||
|  * You must obey the GNU Lesser General Public License in all respects for | ||||
|  * all of the code used other than OpenSSL. | ||||
|  * | ||||
|  * psycopg2 is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public | ||||
|  * License for more details. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef PSYCOPG_GREEN_H | ||||
| #define PSYCOPG_GREEN_H 1 | ||||
| 
 | ||||
| struct PyObject; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define psyco_set_wait_callback_doc \ | ||||
| "set_wait_callback(f) -- Register a callback function to block waiting for data.\n" \ | ||||
| "\n" \ | ||||
| "The callback must should signature :samp:`fun({conn}, {cur}=None)` and\n" \ | ||||
| "is called to wait for data available whenever a blocking function from the\n" \ | ||||
| "libpq is called.  Use `!register_wait_function(None)` to revert to the\n" \ | ||||
| "original behaviour (using blocking libpq functions).\n" \ | ||||
| "\n" \ | ||||
| "The function is an hook to allow coroutine-based libraries (such as\n" \ | ||||
| "eventlet_ or gevent_) to switch when Psycopg is blocked, allowing\n" \ | ||||
| "other coroutines to run concurrently.\n" \ | ||||
| "\n" \ | ||||
| "See `~psycopg2.extras.wait_select()` for an example of a wait callback\n" \ | ||||
| "implementation.\n" | ||||
| 
 | ||||
| HIDDEN PyObject *psyco_set_wait_callback(PyObject *self, PyObject *obj); | ||||
| HIDDEN int psyco_green(void); | ||||
| HIDDEN PyObject *psyco_wait(PyObject *conn, PyObject *curs); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* !defined(PSYCOPG_GREEN_H) */ | ||||
|  | @ -32,6 +32,7 @@ | |||
| #include "psycopg/psycopg.h" | ||||
| #include "psycopg/connection.h" | ||||
| #include "psycopg/cursor.h" | ||||
| #include "psycopg/green.h" | ||||
| #include "psycopg/lobject.h" | ||||
| #include "psycopg/typecast.h" | ||||
| #include "psycopg/microprotocols.h" | ||||
|  | @ -693,6 +694,11 @@ static PyMethodDef psycopgMethods[] = { | |||
|      METH_VARARGS, psyco_IntervalFromMx_doc}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef PSYCOPG_EXTENSIONS | ||||
|     {"set_wait_callback",  (PyCFunction)psyco_set_wait_callback, | ||||
|      METH_O, psyco_set_wait_callback_doc}, | ||||
| #endif | ||||
| 
 | ||||
|     {NULL, NULL, 0, NULL}        /* Sentinel */ | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							|  | @ -343,7 +343,7 @@ sources = [ | |||
|     'adapter_qstring.c', 'adapter_pboolean.c', 'adapter_binary.c', | ||||
|     'adapter_asis.c', 'adapter_list.c', 'adapter_datetime.c', | ||||
|     'adapter_pfloat.c', 'adapter_pdecimal.c', | ||||
|     'utils.c'] | ||||
|     'green.c', 'utils.c'] | ||||
| 
 | ||||
| parser = ConfigParser.ConfigParser() | ||||
| parser.read('setup.cfg') | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user