{-| Module: Network.Starling Copyright: Antoine Latter 2009 Maintainer: Antoine Latter A haskell implementation of the memcahed protocol. This implements the new binary protocol, so it only works with memcached version 1.3 and newer. Example of usage, using the network package to obain a handle, and the OverloadedStrings language extension: > h <- connectTo "filename" $ UnixSocket "filename" > hSetBuffering h NoBuffering > con <- open h > set con "hello" "world" > get con "hello" In the above example we connect to a unix socket in the file \"filename\", set the key \"hello\" to the value \"world\" and then retrieve the value. Operations are thread safe - multiple threads of execution may make concurrent requests on the memcahced connection. Operations are blocking, but do not block other concurrent threads from placing requests on the connection. -} module Network.Starling ( open , close , Connection , Key , Value , Result , ResponseStatus(..) , set , get , delete -- , add -- , replace -- , increment -- , decrement , flush , stats -- , oneStat -- doesn't seem to work for me , version ) where import Network.Starling.Connection import Network.Starling.Core hiding ( get , set , delete , add , replace , increment , decrement , flush , stat , version , quit ) import qualified Network.Starling.Core as Core import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BS type Result a = IO (Either (ResponseStatus, ByteString) a) -- | Set a value in the cache set :: Connection -> Key -> Value -> Result () set con key value = simpleRequest con (Core.set key value) (const ()) -- | Retrive a value from the cache get :: Connection -> Key -> Result ByteString get con key = simpleRequest con (Core.get key) rsBody -- | Delete an entry in the cache delete :: Connection -> Key -> Result () delete con key = simpleRequest con (Core.delete key) (const ()) -- | Delete all entries in the cache flush :: Connection -> Result () flush con = simpleRequest con Core.flush (const ()) simpleRequest :: Connection -> Request -> (Response -> a) -> Result a simpleRequest con req f = do response <- synchRequest con req if rsStatus response == NoError then return . Right . f $ response else return . errorResult $ response errorResult response = Left (rsStatus response, rsBody response) -- | Returns a list of stats about the server in key,value pairs stats :: Connection -> Result [(ByteString,ByteString)] stats con = do resps <- synchRequestMulti con $ Core.stat Nothing if null resps then error "fatal error in Network.Starling.stats" else do let resp = head resps if rsStatus resp == NoError then return . Right . unpackStats $ resps else return $ errorResult resp where unpackStats = filter (\(x,y) -> not (BS.null x && BS.null y)) . map (\response -> (rsKey response, rsBody response)) -- | Returns a single stat. Example: 'stat con "pid"' will return -- the oneStat :: Connection -> Key -> Result ByteString oneStat con key = simpleRequest con (Core.stat $ Just key) rsBody -- | Returns the version of the server version :: Connection -> Result ByteString version con = simpleRequest con Core.version rsBody