@@ -0,0 +1,78 @@
1+{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
3+-----------------------------------------------------------------------------
5+-- Module : Database.HDBC.PostgreSQL.Notification
6+-- Copyright : (c) 2011 Leon P Smith
9+-- Maintainer : leon@melding-monads.com
10+-- Stability : experimental
12+-----------------------------------------------------------------------------
14+module Database.PostgreSQL.Simple.Notification
19+import Control.Concurrent ( threadWaitRead )
20+import Control.Concurrent.MVar ( takeMVar, putMVar )
21+import qualified Data.ByteString as B
22+import Database.PostgreSQL.Simple.Implementation
23+import qualified Database.PostgreSQL.LibPQ as PQ
24+import System.Posix.Types ( CPid )
26+data Notification = Notification
27+ { notificationPid :: CPid
28+ , notificationChannel :: B.ByteString
29+ , notificationData :: B.ByteString
32+errfd = "Database.PostgreSQL.Simple.Notification.getNotification: \
33+ \failed to fetch file descriptor"
34+errconn = "Database.PostgreSQL.Simple.Notification.getNotification: \
37+lockConn :: Connection -> IO (PQ.Connection)
38+lockConn Connection{..} = do
39+ mconn <- takeMVar connectionHandle
42+ putMVar connectionHandle mconn
44+ Just conn -> return conn
46+unlockConn :: Connection -> PQ.Connection -> IO ()
47+unlockConn Connection{..} c = putMVar connectionHandle (Just c)
49+getNotification :: Connection -> IO Notification
50+getNotification conn = do
54+ -- now, I believe the only ways that this code throws an exception is:
55+ -- 1. lockConn/unlockConn when we are blocked on a GC'd MVar
56+ -- 2. threadWaitRead when closeFdWith gets called
57+ -- 3. and if we raise it ourself
58+ -- If 1 happens, then it doesn't matter if the MVar is locked or not,
59+ -- and if 2 or 3 happens then the connection should be unlocked.
61+ mmsg <- PQ.notifies c
67+ Nothing -> fail errfd
71+ _ <- PQ.consumeInput c
72+ -- FIXME? error handling
74+ Just PQ.Notify{..} -> do
76+ return Notification { notificationPid = notifyBePid
77+ , notificationChannel = notifyRelname
78+ , notificationData = notifyExtra }