@@ -407,11 +407,6 @@ the connection is made:
407407 ``db.backend_id``
408408 The process-id of the backend process.
409409
410- ``db.fileno()``
411- Method to get the file descriptor number of the connection's socket. This
412- attribute will not exist if the socket object does not have a ``fileno``
413- attribute. Under normal circumstances, it will be available.
414-
415410 ``db.backend_start``
416411 When backend was started. ``datetime.datetime`` instance.
417412
@@ -421,8 +416,14 @@ the connection is made:
421416 ``db.client_port``
422417 The port of the client that the backend is communicating with.
423418
424- The latter three are collected from pg_stat_activity. If this information is
425- unavailable, the attributes will be `None`.
419+ ``db.fileno()``
420+ Method to get the file descriptor number of the connection's socket. This
421+ method will return `None` if the socket object does not have a ``fileno``
422+ attribute. Under normal circumstances, it will return an `int`.
423+
424+ The ``backend_start``, ``client_address``, and ``client_port`` are collected
425+ from pg_stat_activity. If this information is unavailable, the attributes will
426+ be `None`.
426427
427428
428429Prepared Statements
@@ -461,8 +462,8 @@ be explicitly closed if the statement is to be discarded.
461462Statement objects are one-time objects. Once closed, they can no longer be used.
462463
463464
464- Prepared Statement Interface Points
465- -----------------------------------
465+ Statement Interface Points
466+ --------------------------
466467
467468Prepared statements can be executed just like functions:
468469
@@ -1911,11 +1912,109 @@ Summary of Characteristics
19111912 * When a connection dies or raises an exception, it will be removed from
19121913 the ``nm.connections`` set and added to the ``nm.garbage`` set.
19131914 * The NotificationManager instance will *not* hold any notifications
1914- during an idle event.
1915- (Idle events offer a break point in which the manager may be discarded.)
1915+ during an idle event. Idle events offer a break point in which the manager
1916+ may be discarded.
19161917 * A timeout of zero will cause the iterator to only yield the events
19171918 that are pending right now, and promptly end. However, the same manager
19181919 object may be used again.
19191920 * A notification triple is a tuple consisting of ``(channel, payload, pid)``.
19201921 * Connections may be added and removed from the ``nm.connections`` set at
19211922 any time.
1923+
1924+
1925+ Advisory Locks
1926+ ==============
1927+
1928+ `Explicit Locking in PostgreSQL <http://www.postgresql.org/docs/current/static/explicit-locking.html#ADVISORY-LOCKS>`_.
1929+
1930+ PostgreSQL's advisory locks offers a cooperative synchronization primitive.
1931+ These are used in cases where an application needs access to a resource, but
1932+ using table locks may cause interference with other operations that can be
1933+ safely performed alongside the application-level, exclusive operation.
1934+
1935+ Advisory locks can be used by directly executing the stored procedures in the
1936+ database or by using the :class:`postgresql.alock.ALock` subclasses, which
1937+ provides a context manager that uses those stored procedures.
1938+
1939+ Currently, only two subclasses exists, each representing the lock mode
1940+ supported by PostgreSQL's advisory locks:
1941+
1942+ * :class:`postgresql.alock.ShareLock`
1943+ * :class:`postgresql.alock.ExclusiveLock`
1944+
1945+
1946+ Acquiring ALocks
1947+ ----------------
1948+
1949+ An ALock instance represents a sequence of advisory locks. A single ALock can
1950+ acquire and release multiple advisory locks by creating the instance with
1951+ multiple lock identifiers::
1952+
1953+ >>> from postgresql import alock
1954+ >>> table1_oid = 192842
1955+ >>> table2_oid = 192849
1956+ >>> l = alock.ExclusiveLock(db, (table1_oid, 0), (table2_oid, 0))
1957+ >>> l.acquire()
1958+ >>> ...
1959+ >>> l.release()
1960+
1961+ :class:`postgresql.alock.ALock` is similar to :class:`threading.RLock`; in
1962+ order for an ALock to be released, it must be released the number of times it
1963+ has been acquired. ALocks are associated with and survived by their session.
1964+ Much like how RLocks are associated with the thread they are acquired in:
1965+ acquiring an ALock again will merely increment its count.
1966+
1967+ PostgreSQL allows advisory locks to be identified using a pair of `int4` or a
1968+ single `int8`. ALock instances represent a *sequence* of those identifiers::
1969+
1970+ >>> from postgresql import alock
1971+ >>> ids = [(0,0), 0, 1]
1972+ >>> with alock.ShareLock(db, *ids):
1973+ ... ...
1974+
1975+ Both types of identifiers may be used within the same ALock, and, regardless of
1976+ their type, will be aquired in the order that they were given to the class'
1977+ constructor. In the above example, ``(0,0)`` is acquired first, then ``0``, and
1978+ lastly ``1``.
1979+
1980+ `postgresql.alock.ALock` subclasses:
1981+
1982+ ``postgresql.alock.ExclusiveLock(database, *identifiers)``
1983+ Instantiate an ALock object representing the `identifiers` for use with the
1984+ `database`. Exclusive locks will conflict with other exclusive locks and share
1985+ locks.
1986+
1987+ ``postgresql.alock.ShareLock(database, *identifiers)``
1988+ Instantiate an ALock object representing the `identifiers` for use with the
1989+ `database`. Share locks can be acquired when a share lock with the same
1990+ identifier has been acquired by another backend. However, an exclusive lock
1991+ with the same identifier will conflict.
1992+
1993+
1994+ Advisory Lock Interface Points
1995+ ------------------------------
1996+
1997+ Methods and properties available on :class:`postgresql.alock.ALock` instances:
1998+
1999+ ``alock.acquire(blocking = True)``
2000+ Acquire the advisory locks represented by the ``alock`` object. If blocking is
2001+ `True`, the default, the method will block until locks on *all* the
2002+ identifiers have been acquired.
2003+
2004+ If blocking is `False`, acquisition may not block, and success will be
2005+ indicated by the returned object: `True` if *all* lock identifiers were
2006+ acquired and `False` if any of the lock identifiers could not be acquired.
2007+
2008+ ``alock.release()``
2009+ Release the advisory locks represented by the ``alock`` object. If the lock
2010+ has not been acquired, a `RuntimeError` will be raised.
2011+
2012+ ``alock.locked()``
2013+ Returns a boolean describing whether the locks are held or not. This will
2014+ return `False` if the lock connection has been closed.
2015+
2016+ ``alock.__enter__()``
2017+ Alias to ``acquire``; context manager protocol. Always blocking.
2018+
2019+ ``alock.__exit__(typ, val, tb)``
2020+ Alias to ``release``; context manager protocol.
0 commit comments