packages feed

mongoDB 1.2.0 → 1.3.0

raw patch · 8 files changed

+299/−213 lines, 8 filesdep +textdep ~bsonnew-uploader

Dependencies added: text

Dependency ranges changed: bson

Files

Database/MongoDB/Admin.hs view
@@ -5,9 +5,11 @@ module Database.MongoDB.Admin ( 	-- * Admin 	-- ** Collection-	CollectionOption(..), createCollection, renameCollection, dropCollection, validateCollection,+	CollectionOption(..), createCollection, renameCollection, dropCollection,+    validateCollection, 	-- ** Index-	Index(..), IndexName, index, ensureIndex, createIndex, dropIndex, getIndexes, dropIndexes,+	Index(..), IndexName, index, ensureIndex, createIndex, dropIndex,+    getIndexes, dropIndexes, 	-- ** User 	allUsers, addUser, removeUser, 	-- ** Database@@ -27,20 +29,30 @@  import Prelude hiding (lookup) import Control.Applicative ((<$>))-import Database.MongoDB.Internal.Protocol (pwHash, pwKey)-import Database.MongoDB.Connection (Host, showHostPort)-import Database.MongoDB.Query-import Data.Bson-import Data.UString (pack, append, intercalate)-import Control.Monad.Reader-import qualified Data.HashTable as T-import Data.IORef-import qualified Data.Set as S-import System.IO.Unsafe (unsafePerformIO) import Control.Concurrent (forkIO, threadDelay)-import Database.MongoDB.Internal.Util (MonadIO', (<.>), true1)+import Control.Monad (forever, unless)+import Data.IORef (IORef, newIORef, readIORef, writeIORef)+import Data.Set (Set)+import System.IO.Unsafe (unsafePerformIO)++import qualified Data.HashTable as H+import qualified Data.Set as Set++import Control.Monad.Trans (MonadIO, liftIO) import Control.Monad.Trans.Control (MonadBaseControl)+import Data.Bson (Document, Field(..), at, (=:), (=?), exclude, merge)+import Data.Text (Text) +import qualified Data.Text as T++import Database.MongoDB.Connection (Host, showHostPort)+import Database.MongoDB.Internal.Protocol (pwHash, pwKey)+import Database.MongoDB.Internal.Util (MonadIO', (<.>), true1)+import Database.MongoDB.Query (Action, Database, Collection, Username, Password,+                               Order, Query(..), accessMode, master, runCommand,+                               useDb, thisDatabase, rest, select, find, findOne,+                               insert_, save, delete)+ -- * Admin  -- ** Collection@@ -68,7 +80,7 @@ 	resetIndexCache 	r <- runCommand ["drop" =: coll] 	if true1 "ok" r then return True else do-		if at "errmsg" r == ("ns not found" :: UString) then return False else+		if at "errmsg" r == ("ns not found" :: Text) then return False else 			fail $ "dropCollection failed: " ++ show r  validateCollection :: (MonadIO' m) => Collection -> Action m Document@@ -77,7 +89,7 @@  -- ** Index -type IndexName = UString+type IndexName = Text  data Index = Index { 	iColl :: Collection,@@ -100,17 +112,17 @@ index coll keys = Index coll keys (genName keys) False False  genName :: Order -> IndexName-genName keys = intercalate "_" (map f keys)  where-	f (k := v) = k `append` "_" `append` pack (show v)+genName keys = T.intercalate "_" (map f keys)  where+	f (k := v) = k `T.append` "_" `T.append` T.pack (show v)  ensureIndex :: (MonadIO' m) => Index -> Action m () -- ^ Create index if we did not already create one. May be called repeatedly with practically no performance hit, because we remember if we already called this for the same index (although this memory gets wiped out every 15 minutes, in case another client drops the index and we want to create it again). ensureIndex idx = let k = (iColl idx, iName idx) in do 	icache <- fetchIndexCache 	set <- liftIO (readIORef icache)-	unless (S.member k set) $ do+	unless (Set.member k set) $ do 		accessMode master (createIndex idx)-		liftIO $ writeIORef icache (S.insert k set)+		liftIO $ writeIORef icache (Set.insert k set)  createIndex :: (MonadIO' m) => Index -> Action m () -- ^ Create index on the server. This call goes to the server every time.@@ -132,46 +144,46 @@ -- ^ Drop all indexes on this collection dropIndexes coll = do 	resetIndexCache-	runCommand ["deleteIndexes" =: coll, "index" =: ("*" :: UString)]+	runCommand ["deleteIndexes" =: coll, "index" =: ("*" :: Text)]  -- *** Index cache -type DbIndexCache = T.HashTable Database IndexCache+type DbIndexCache = H.HashTable Database IndexCache -- ^ Cache the indexes we create so repeatedly calling ensureIndex only hits database the first time. Clear cache every once in a while so if someone else deletes index we will recreate it on ensureIndex. -type IndexCache = IORef (S.Set (Collection, IndexName))+type IndexCache = IORef (Set (Collection, IndexName))  dbIndexCache :: DbIndexCache -- ^ initialize cache and fork thread that clears it every 15 minutes dbIndexCache = unsafePerformIO $ do-	table <- T.new (==) (T.hashString . unpack)+	table <- H.new (==) (H.hashString . T.unpack) 	_ <- forkIO . forever $ threadDelay 900000000 >> clearDbIndexCache 	return table {-# NOINLINE dbIndexCache #-}  clearDbIndexCache :: IO () clearDbIndexCache = do-	keys <- map fst <$> T.toList dbIndexCache-	mapM_ (T.delete dbIndexCache) keys+	keys <- map fst <$> H.toList dbIndexCache+	mapM_ (H.delete dbIndexCache) keys  fetchIndexCache :: (MonadIO m) => Action m IndexCache -- ^ Get index cache for current database fetchIndexCache = do 	db <- thisDatabase 	liftIO $ do-		mc <- T.lookup dbIndexCache db+		mc <- H.lookup dbIndexCache db 		maybe (newIdxCache db) return mc  where 	newIdxCache db = do-		idx <- newIORef S.empty-		T.insert dbIndexCache db idx+		idx <- newIORef Set.empty+		H.insert dbIndexCache db idx 		return idx  resetIndexCache :: (MonadIO m) => Action m () -- ^ reset index cache for current database resetIndexCache = do 	icache <- fetchIndexCache-	liftIO (writeIORef icache S.empty)+	liftIO (writeIORef icache Set.empty)  -- ** User @@ -223,7 +235,7 @@ serverBuildInfo :: (MonadIO' m) => Action m Document serverBuildInfo = useDb admin $ runCommand ["buildinfo" =: (1 :: Int)] -serverVersion :: (MonadIO' m) => Action m UString+serverVersion :: (MonadIO' m) => Action m Text serverVersion = at "version" <$> serverBuildInfo  -- * Diagnostics@@ -248,7 +260,7 @@ 	xs <- mapM isize =<< getIndexes coll 	return (foldl (+) x xs)  where-	isize idx = at "storageSize" <$> collectionStats (coll `append` ".$" `append` at "name" idx)+	isize idx = at "storageSize" <$> collectionStats (coll `T.append` ".$" `T.append` at "name" idx)  -- ** Profiling 
Database/MongoDB/Connection.hs view
@@ -8,33 +8,44 @@ 	-- * Connection 	Pipe, close, isClosed, 	-- * Server-	Host(..), PortID(..), defaultPort, host, showHostPort, readHostPort, readHostPortM,-	globalConnectTimeout, connect, connect',+	Host(..), PortID(..), defaultPort, host, showHostPort, readHostPort,+    readHostPortM, globalConnectTimeout, connect, connect', 	-- * Replica Set 	ReplicaSetName, openReplicaSet, openReplicaSet',-	ReplicaSet, primary, secondaryOk, closeReplicaSet, replSetName+	ReplicaSet, primary, secondaryOk, routedHost, closeReplicaSet, replSetName ) where  import Prelude hiding (lookup)-import Database.MongoDB.Internal.Protocol (Pipe, newPipe)-import System.IO.Pipeline (IOE, close, isClosed)-import Control.Exception as E (try)+import Data.IORef (IORef, newIORef, readIORef)+import Data.List (intersect, partition, (\\), delete)+import Control.Applicative ((<$>))+import Control.Monad (forM_) import Network (HostName, PortID(..), connectTo)-import Text.ParserCombinators.Parsec as T (parse, many1, letter, digit, char, eof, spaces, try, (<|>))+import System.IO.Unsafe (unsafePerformIO)+import System.Timeout (timeout)+import Text.ParserCombinators.Parsec (parse, many1, letter, digit, char, eof,+                                      spaces, try, (<|>))+import qualified Control.Exception as E+import qualified Data.List as List++ import Control.Monad.Identity (runIdentity) import Control.Monad.Error (ErrorT(..), lift, throwError)-import Control.Concurrent.MVar.Lifted-import Control.Monad (forM_)-import Control.Applicative ((<$>))-import Data.UString (UString, unpack)-import Data.Bson as D (Document, lookup, at, (=:))-import Database.MongoDB.Query (access, slaveOk, Failure(ConnectionFailure), Command, runCommand)-import Database.MongoDB.Internal.Util (untilSuccess, liftIOE, runIOE, updateAssocs, shuffle)-import Data.List as L (lookup, intersect, partition, (\\), delete)-import Data.IORef (IORef, newIORef, readIORef)-import System.Timeout (timeout)-import System.IO.Unsafe (unsafePerformIO)+import Control.Concurrent.MVar.Lifted (MVar, newMVar, withMVar, modifyMVar,+                                       readMVar)+import Data.Bson (Document, at, (=:))+import Data.Text (Text) +import qualified Data.Bson as B+import qualified Data.Text as T++import Database.MongoDB.Internal.Protocol (Pipe, newPipe)+import Database.MongoDB.Internal.Util (untilSuccess, liftIOE, runIOE,+                                       updateAssocs, shuffle, mergesortM)+import Database.MongoDB.Query (Command, Failure(ConnectionFailure), access,+                              slaveOk, runCommand)+import System.IO.Pipeline (IOE, close, isClosed)+ adminCommand :: Command -> Pipe -> IOE Document -- ^ Run command against admin database on server connected to pipe. Fail if connection fails. adminCommand cmd pipe =@@ -74,7 +85,7 @@ 	parser = do 		spaces 		h <- hostname-		T.try (spaces >> eof >> return (host h)) <|> do+		try (spaces >> eof >> return (host h)) <|> do 			_ <- char ':' 			port :: Int <- read <$> many1 digit 			spaces >> eof@@ -105,12 +116,12 @@  -- * Replica Set -type ReplicaSetName = UString+type ReplicaSetName = Text  -- | Maintains a connection (created on demand) to each server in the named replica set data ReplicaSet = ReplicaSet ReplicaSetName (MVar [(Host, Maybe Pipe)]) Secs -replSetName :: ReplicaSet -> UString+replSetName :: ReplicaSet -> Text -- ^ name of connected replica set replSetName (ReplicaSet rsName _ _) = rsName @@ -136,7 +147,7 @@ 	mHost <- statedPrimary <$> updateMembers rs 	case mHost of 		Just host' -> connection rs Nothing host'-		Nothing -> throwError $ userError $ "replica set " ++ unpack rsName ++ " has no primary"+		Nothing -> throwError $ userError $ "replica set " ++ T.unpack rsName ++ " has no primary"  secondaryOk :: ReplicaSet -> IOE Pipe -- ^ Return connection to a random secondary, or primary if no secondaries available.@@ -146,12 +157,21 @@ 	let hosts' = maybe hosts (\p -> delete p hosts ++ [p]) (statedPrimary info) 	untilSuccess (connection rs Nothing) hosts' +routedHost :: ((Host, Bool) -> (Host, Bool) -> IOE Ordering) -> ReplicaSet -> IOE Pipe+-- ^ Return a connection to a host using a user-supplied sorting function, which sorts based on a tuple containing the host and a boolean indicating whether the host is primary.+routedHost f rs = do+  info <- updateMembers rs+  hosts <- lift $ shuffle (possibleHosts info)+  let addIsPrimary h = (h, if Just h == statedPrimary info then True else False)+  hosts' <- mergesortM (\a b -> f (addIsPrimary a) (addIsPrimary b)) hosts+  untilSuccess (connection rs Nothing) hosts'+ type ReplicaInfo = (Host, Document) -- ^ Result of isMaster command on host in replica set. Returned fields are: setName, ismaster, secondary, hosts, [primary]. primary only present when ismaster = false  statedPrimary :: ReplicaInfo -> Maybe Host -- ^ Primary of replica set or Nothing if there isn't one-statedPrimary (host', info) = if (at "ismaster" info) then Just host' else readHostPort <$> D.lookup "primary" info+statedPrimary (host', info) = if (at "ismaster" info) then Just host' else readHostPort <$> B.lookup "primary" info  possibleHosts :: ReplicaInfo -> [Host] -- ^ Non-arbiter, non-hidden members of replica set@@ -176,9 +196,9 @@ fetchReplicaInfo rs@(ReplicaSet rsName _ _) (host', mPipe) = do 	pipe <- connection rs mPipe host' 	info <- adminCommand ["isMaster" =: (1 :: Int)] pipe-	case D.lookup "setName" info of-		Nothing -> throwError $ userError $ show host' ++ " not a member of any replica set, including " ++ unpack rsName ++ ": " ++ show info-		Just setName | setName /= rsName -> throwError $ userError $ show host' ++ " not a member of replica set " ++ unpack rsName ++ ": " ++ show info+	case B.lookup "setName" info of+		Nothing -> throwError $ userError $ show host' ++ " not a member of any replica set, including " ++ T.unpack rsName ++ ": " ++ show info+		Just setName | setName /= rsName -> throwError $ userError $ show host' ++ " not a member of replica set " ++ T.unpack rsName ++ ": " ++ show info 		Just _ -> return (host', info)  connection :: ReplicaSet -> Maybe Pipe -> Host -> IOE Pipe@@ -188,7 +208,7 @@  where  	conn = 	modifyMVar vMembers $ \members -> do 		let new = connect' timeoutSecs host' >>= \pipe -> return (updateAssocs host' (Just pipe) members, pipe)-		case L.lookup host' members of+		case List.lookup host' members of 			Just (Just pipe) -> lift (isClosed pipe) >>= \bad -> if bad then new else return (members, pipe) 			_ -> new 
Database/MongoDB/Internal/Protocol.hs view
@@ -1,8 +1,12 @@-{-| Low-level messaging between this client and the MongoDB server, see Mongo Wire Protocol (<http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol>).--This module is not intended for direct use. Use the high-level interface at "Database.MongoDB.Query" and "Database.MongoDB.Connection" instead. -}+-- | Low-level messaging between this client and the MongoDB server, see Mongo+-- Wire Protocol (<http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol>).+--+-- This module is not intended for direct use. Use the high-level interface at+-- "Database.MongoDB.Query" and "Database.MongoDB.Connection" instead. -{-# LANGUAGE RecordWildCards, StandaloneDeriving, OverloadedStrings, FlexibleContexts, TupleSections, TypeSynonymInstances, MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}+{-# LANGUAGE RecordWildCards, StandaloneDeriving, OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts, TupleSections, TypeSynonymInstances #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}  module Database.MongoDB.Internal.Protocol ( 	FullCollection,@@ -18,28 +22,36 @@ 	Username, Password, Nonce, pwHash, pwKey ) where -import Prelude as X import Control.Applicative ((<$>)) import Control.Arrow ((***))-import Data.ByteString.Lazy as B (length, hPut)-import System.IO.Pipeline (IOE, Pipeline, newPipeline, IOStream(..))-import qualified System.IO.Pipeline as P (send, call)-import System.IO (Handle, hClose)-import Data.Bson (Document, UString)-import Data.Bson.Binary-import Data.Binary.Put-import Data.Binary.Get-import Data.Int-import Data.Bits-import Data.IORef+import Control.Exception (try)+import Control.Monad (forM_, replicateM, unless)+import Data.Binary.Get (Get, runGet)+import Data.Binary.Put (Put, runPut)+import Data.Bits (bit, testBit)+import Data.Int (Int32, Int64)+import Data.IORef (IORef, newIORef, atomicModifyIORef)+import System.IO (Handle, hClose, hFlush) import System.IO.Unsafe (unsafePerformIO)-import qualified Crypto.Hash.MD5 as MD5 (hash)-import Data.UString as U (pack, append, toByteString)-import Control.Exception as E (try)-import Control.Monad.Error-import System.IO (hFlush)++import qualified Data.ByteString.Lazy as L++import Control.Monad.Error (ErrorT(..))+import Control.Monad.Trans (MonadIO, liftIO)+import Data.Bson (Document)+import Data.Bson.Binary (getDocument, putDocument, getInt32, putInt32, getInt64,+                         putInt64, putCString)+import Data.Text (Text)++import qualified Crypto.Hash.MD5 as MD5+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+ import Database.MongoDB.Internal.Util (whenJust, hGetN, bitOr, byteStringHex)+import System.IO.Pipeline (IOE, Pipeline, newPipeline, IOStream(..)) +import qualified System.IO.Pipeline as P+ -- * Pipe  type Pipe = Pipeline Response Message@@ -71,17 +83,17 @@  writeMessage :: Handle -> Message -> IOE () -- ^ Write message to socket-writeMessage handle (notices, mRequest) = ErrorT . E.try $ do+writeMessage handle (notices, mRequest) = ErrorT . try $ do 	forM_ notices $ \n -> writeReq . (Left n,) =<< genRequestId 	whenJust mRequest $ writeReq . (Right *** id) 	hFlush handle  where 	writeReq (e, requestId) = do-		hPut handle lenBytes-		hPut handle bytes+		L.hPut handle lenBytes+		L.hPut handle bytes 	 where 		bytes = runPut $ (either putNotice putRequest e) requestId-		lenBytes = encodeSize . toEnum . fromEnum $ B.length bytes+		lenBytes = encodeSize . toEnum . fromEnum $ L.length bytes 	encodeSize = runPut . putInt32 . (+ 4)  type Response = (ResponseTo, Reply)@@ -89,13 +101,13 @@  readMessage :: Handle -> IOE Response -- ^ read response from socket-readMessage handle = ErrorT $ E.try readResp  where+readMessage handle = ErrorT $ try readResp  where 	readResp = do 		len <- fromEnum . decodeSize <$> hGetN handle 4 		runGet getReply <$> hGetN handle len 	decodeSize = subtract 4 . runGet getInt32 -type FullCollection = UString+type FullCollection = Text -- ^ Database name and collection name with period (.) in between. Eg. \"myDb.myCollection\"  -- ** Header@@ -194,7 +206,7 @@ 			putDocument dSelector 		KillCursors{..} -> do 			putInt32 0-			putInt32 $ toEnum (X.length kCursorIds)+			putInt32 $ toEnum (length kCursorIds) 			mapM_ putInt64 kCursorIds  iBit :: InsertOption -> Int32@@ -319,15 +331,15 @@  -- * Authentication -type Username = UString-type Password = UString-type Nonce = UString+type Username = Text+type Password = Text+type Nonce = Text -pwHash :: Username -> Password -> UString-pwHash u p = pack . byteStringHex . MD5.hash . toByteString $ u `U.append` ":mongo:" `U.append` p+pwHash :: Username -> Password -> Text+pwHash u p = T.pack . byteStringHex . MD5.hash . TE.encodeUtf8 $ u `T.append` ":mongo:" `T.append` p -pwKey :: Nonce -> Username -> Password -> UString-pwKey n u p = pack . byteStringHex . MD5.hash . toByteString . U.append n . U.append u $ pwHash u p+pwKey :: Nonce -> Username -> Password -> Text+pwKey n u p = T.pack . byteStringHex . MD5.hash . TE.encodeUtf8 . T.append n . T.append u $ pwHash u p   {- Authors: Tony Hannan <tony@10gen.com>
Database/MongoDB/Internal/Util.hs view
@@ -1,27 +1,34 @@ -- | Miscellaneous general functions and Show, Eq, and Ord instances for PortID  {-# LANGUAGE FlexibleInstances, UndecidableInstances, StandaloneDeriving #-}+-- PortID instances+{-# OPTIONS_GHC -fno-warn-orphans #-}  module Database.MongoDB.Internal.Util where  import Control.Applicative (Applicative(..), (<$>))-import Network (PortID(..))-import Data.UString as U (cons, append)-import Data.Bits (Bits, (.|.))-import Data.Bson-import Data.ByteString.Lazy as S (ByteString, length, append, hGet)-import System.IO (Handle)-import System.IO.Error (mkIOError, eofErrorType)-import Control.Exception (assert)-import Control.Monad.Error import Control.Arrow (left)-import qualified Data.ByteString as BS (ByteString, unpack)+import Control.Exception (assert)+import Control.Monad (liftM, liftM2)+import Data.Bits (Bits, (.|.)) import Data.Word (Word8)+import Network (PortID(..)) import Numeric (showHex)-import System.Random.Shuffle (shuffle')+import System.IO (Handle)+import System.IO.Error (mkIOError, eofErrorType) import System.Random (newStdGen)-import Data.List as L (length)+import System.Random.Shuffle (shuffle') +import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString as S++import Control.Monad.Error (MonadError(..), ErrorT(..), Error(..))+import Control.Monad.Trans (MonadIO, liftIO)+import Data.Bson+import Data.Text (Text)++import qualified Data.Text as T+ deriving instance Show PortID deriving instance Eq PortID deriving instance Ord PortID@@ -30,9 +37,36 @@ class (MonadIO m, Applicative m, Functor m) => MonadIO' m instance (MonadIO m, Applicative m, Functor m) => MonadIO' m +-- | A monadic sort implementation derived from the non-monadic one in ghc's Prelude+mergesortM :: Monad m => (a -> a -> m Ordering) -> [a] -> m [a]+mergesortM cmp = mergesortM' cmp . map wrap++mergesortM' :: Monad m => (a -> a -> m Ordering) -> [[a]] -> m [a]+mergesortM' _  [] = return []+mergesortM' _  [xs] = return xs+mergesortM' cmp xss = mergesortM' cmp =<< (merge_pairsM cmp xss)++merge_pairsM :: Monad m => (a -> a -> m Ordering) -> [[a]] -> m [[a]]+merge_pairsM _   [] = return []+merge_pairsM _   [xs] = return [xs]+merge_pairsM cmp (xs:ys:xss) = liftM2 (:) (mergeM cmp xs ys) (merge_pairsM cmp xss)++mergeM :: Monad m => (a -> a -> m Ordering) -> [a] -> [a] -> m [a]+mergeM _   [] ys = return ys+mergeM _   xs [] = return xs+mergeM cmp (x:xs) (y:ys)+ = do+     c <- x `cmp` y+     case c of+        GT -> liftM (y:) (mergeM cmp (x:xs)   ys)+        _  -> liftM (x:) (mergeM cmp    xs (y:ys))++wrap :: a -> [a]+wrap x = [x]+ shuffle :: [a] -> IO [a] -- ^ Randomly shuffle items in list-shuffle list = shuffle' list (L.length list) <$> newStdGen+shuffle list = shuffle' list (length list) <$> newStdGen  loop :: (Functor m, Monad m) => m (Maybe a) -> m [a] -- ^ Repeatedy execute action, collecting results, until it returns Nothing@@ -67,9 +101,9 @@ -- ^ bit-or all numbers together bitOr = foldl (.|.) 0 -(<.>) :: UString -> UString -> UString+(<.>) :: Text -> Text -> Text -- ^ Concat first and second together with period in between. Eg. @\"hello\" \<.\> \"world\" = \"hello.world\"@-a <.> b = U.append a (cons '.' b)+a <.> b = T.append a (T.cons '.' b)  true1 :: Label -> Document -> Bool -- ^ Is field's value a 1 or True (MongoDB use both Int and Bools for truth values). Error if field not in document or field not a Num or Bool.@@ -80,18 +114,18 @@ 	Int64 n -> n == 1 	_ -> error $ "expected " ++ show k ++ " to be Num or Bool in " ++ show doc -hGetN :: Handle -> Int -> IO ByteString+hGetN :: Handle -> Int -> IO L.ByteString -- ^ Read N bytes from hande, blocking until all N bytes are read. If EOF is reached before N bytes then raise EOF exception. hGetN h n = assert (n >= 0) $ do-	bytes <- hGet h n-	let x = fromEnum $ S.length bytes+	bytes <- L.hGet h n+	let x = fromEnum $ L.length bytes 	if x >= n then return bytes 		else if x == 0 then ioError (mkIOError eofErrorType "hGetN" (Just h) Nothing)-			else S.append bytes <$> hGetN h (n - x)+			else L.append bytes <$> hGetN h (n - x) -byteStringHex :: BS.ByteString -> String+byteStringHex :: S.ByteString -> String -- ^ Hexadecimal string representation of a byte string. Each byte yields two hexadecimal characters.-byteStringHex = concatMap byteHex . BS.unpack+byteStringHex = concatMap byteHex . S.unpack  byteHex :: Word8 -> String -- ^ Two char hexadecimal representation of byte
Database/MongoDB/Query.hs view
@@ -25,38 +25,58 @@ 	delete, deleteOne, 	-- * Read 	-- ** Query-	Query(..), QueryOption(NoCursorTimeout, TailableCursor, AwaitData, Partial), Projector, Limit, Order, BatchSize,+	Query(..), QueryOption(NoCursorTimeout, TailableCursor, AwaitData, Partial),+    Projector, Limit, Order, BatchSize, 	explain, find, findOne, fetch, count, distinct, 	-- *** Cursor 	Cursor, nextBatch, next, nextN, rest, closeCursor, isCursorClosed, 	-- ** Group 	Group(..), GroupKey(..), group, 	-- ** MapReduce-	MapReduce(..), MapFun, ReduceFun, FinalizeFun, MROut(..), MRMerge(..), MRResult, mapReduce, runMR, runMR',+	MapReduce(..), MapFun, ReduceFun, FinalizeFun, MROut(..), MRMerge(..),+    MRResult, mapReduce, runMR, runMR', 	-- * Command 	Command, runCommand, runCommand1, 	eval, ) where -import Prelude as X hiding (lookup)-import Data.UString as U (UString, dropWhile, any, tail)-import Data.Bson (Document, at, valueAt, lookup, look, Field(..), (=:), (=?), Label, Value(String,Doc), Javascript, genObjectId)-import Database.MongoDB.Internal.Protocol (Pipe, Notice(..), Request(GetMore, qOptions, qFullCollection, qSkip, qBatchSize, qSelector, qProjector), Reply(..), QueryOption(..), ResponseFlag(..), InsertOption(..), UpdateOption(..), DeleteOption(..), CursorId, FullCollection, Username, Password, pwKey)-import qualified Database.MongoDB.Internal.Protocol as P (send, call, Request(Query))-import Database.MongoDB.Internal.Util (MonadIO', loop, liftIOE, true1, (<.>))-import Control.Concurrent.MVar.Lifted-import Control.Monad.Error-import Control.Monad.Reader-import Control.Monad.State (StateT)-import Control.Monad.Writer (WriterT, Monoid)-import Control.Monad.RWS (RWST)-import Control.Monad.Base (MonadBase(liftBase))-import Control.Monad.Trans.Control (ComposeSt, MonadBaseControl(..), MonadTransControl(..), StM, StT, defaultLiftBaseWith, defaultRestoreM)+import Prelude hiding (lookup) import Control.Applicative (Applicative, (<$>))-import Data.Maybe (listToMaybe, catMaybes)+import Control.Monad (unless, replicateM, liftM) import Data.Int (Int32)+import Data.Maybe (listToMaybe, catMaybes) import Data.Word (Word32) +import Control.Concurrent.MVar.Lifted (MVar, newMVar, addMVarFinalizer,+                                       readMVar, modifyMVar)+import Control.Monad.Base (MonadBase(liftBase))+import Control.Monad.Error (ErrorT, Error(..), MonadError, runErrorT,+                            throwError)+import Control.Monad.Reader (ReaderT, runReaderT, ask, asks, local)+import Control.Monad.RWS (RWST)+import Control.Monad.State (StateT)+import Control.Monad.Trans (MonadIO, MonadTrans, lift, liftIO)+import Control.Monad.Trans.Control (ComposeSt, MonadBaseControl(..),+                                    MonadTransControl(..), StM, StT,+                                    defaultLiftBaseWith, defaultRestoreM)+import Control.Monad.Writer (WriterT, Monoid)+import Data.Bson (Document, Field(..), Label, Value(String,Doc), Javascript,+                  at, valueAt, lookup, look, genObjectId, (=:), (=?))+import Data.Text (Text)+import qualified Data.Text as T++import Database.MongoDB.Internal.Protocol (Reply(..), QueryOption(..),+                                           ResponseFlag(..), InsertOption(..),+                                           UpdateOption(..), DeleteOption(..),+                                           CursorId, FullCollection, Username,+                                           Password, Pipe, Notice(..),+                                           Request(GetMore, qOptions, qSkip,+                                           qFullCollection, qBatchSize,+                                           qSelector, qProjector),+                                           pwKey)+import Database.MongoDB.Internal.Util (MonadIO', loop, liftIOE, true1, (<.>))+import qualified Database.MongoDB.Internal.Protocol as P+ -- * Monad  newtype Action m a = Action {unAction :: ErrorT Failure (ReaderT Context m) a}@@ -106,6 +126,7 @@ 	 ReadStaleOk  -- ^ Read-only action, reading stale data from a slave is OK. 	| UnconfirmedWrites  -- ^ Read-write action, slave not OK, every write is fire & forget. 	| ConfirmWrites GetLastError  -- ^ Read-write action, slave not OK, every write is confirmed with getLastError.+    deriving Show  type GetLastError = Document -- ^ Parameters for getLastError command. For example @[\"w\" =: 2]@ tells the server to wait for the write to reach at least two servers in replica set before acknowledging. See <http://www.mongodb.org/display/DOCS/Last+Error+Commands> for more options.@@ -183,7 +204,7 @@  -- * Database -type Database = UString+type Database = Text  allDatabases :: (MonadIO' m) => Action m [Database] -- ^ List all databases residing on server@@ -207,7 +228,7 @@  -- * Collection -type Collection = UString+type Collection = Text -- ^ Collection name (not prefixed with database)  allCollections :: (MonadIO m, MonadBaseControl IO m, Functor m) => Action m [Collection]@@ -217,8 +238,8 @@ 	docs <- rest =<< find (query [] "system.namespaces") {sort = ["name" =: (1 :: Int)]} 	return . filter (not . isSpecial db) . map dropDbPrefix $ map (at "name") docs  where- 	dropDbPrefix = U.tail . U.dropWhile (/= '.')- 	isSpecial db col = U.any (== '$') col && db <.> col /= "local.oplog.$main"+ 	dropDbPrefix = T.tail . T.dropWhile (/= '.')+ 	isSpecial db col = T.any (== '$') col && db <.> col /= "local.oplog.$main"  -- * Selection @@ -296,7 +317,7 @@  assignId :: Document -> IO Document -- ^ Assign a unique value to _id field if missing-assignId doc = if X.any (("_id" ==) . label) doc+assignId doc = if any (("_id" ==) . label) doc 	then return doc 	else (\oid -> ("_id" =: oid) : doc) <$> genObjectId @@ -669,7 +690,7 @@ runCommand c = maybe err id <$> findOne (query c "$cmd") where 	err = error $ "Nothing returned for command: " ++ show c -runCommand1 :: (MonadIO' m) => UString -> Action m Document+runCommand1 :: (MonadIO' m) => Text -> Action m Document -- ^ @runCommand1 foo = runCommand [foo =: 1]@ runCommand1 c = runCommand [c =: (1 :: Int)] 
System/IO/Pipeline.hs view
@@ -13,11 +13,15 @@ ) where  import Prelude hiding (length)-import GHC.Conc (ThreadStatus(..), threadStatus) import Control.Concurrent (ThreadId, forkIO, killThread)-import Control.Concurrent.Chan-import Control.Concurrent.MVar.Lifted-import Control.Monad.Error+import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)+import Control.Monad (forever)+import GHC.Conc (ThreadStatus(..), threadStatus)++import Control.Monad.Trans (liftIO)+import Control.Concurrent.MVar.Lifted (MVar, newEmptyMVar, newMVar, withMVar,+                                       putMVar, readMVar, addMVarFinalizer)+import Control.Monad.Error (ErrorT(ErrorT), runErrorT)  onException :: (Monad m) => ErrorT e m a -> m () -> ErrorT e m a -- ^ If first action throws an exception then run second action then re-throw
System/IO/Pool.hs view
@@ -5,12 +5,15 @@ module System.IO.Pool where  import Control.Applicative ((<$>))-import Control.Concurrent.MVar.Lifted-import Data.Array.IO+import Control.Exception (assert)+import Data.Array.IO (IOArray, readArray, writeArray, newArray, newListArray,+                      getElems, getBounds, rangeSize, range) import Data.Maybe (catMaybes)-import Control.Monad.Error import System.Random (randomRIO)-import Control.Exception (assert)++import Control.Concurrent.MVar.Lifted (MVar, newMVar, withMVar, modifyMVar_)+import Control.Monad.Error (ErrorT, Error)+import Control.Monad.Trans (liftIO)  -- | Creator, destroyer, and checker of resources of type r. Creator may throw error or type e. data Factory e r = Factory {
mongoDB.cabal view
@@ -1,68 +1,48 @@-name: mongoDB-version: 1.2.0-build-type: Simple-license: OtherLicense-license-file: LICENSE-copyright: Copyright (c) 2010-2012 10gen Inc.-author: Tony Hannan-maintainer: Tony Hannan <tonyhannan@gmail.com>-build-depends:-    array -any,-    base <5,-    binary -any,-    bson -any,-    bytestring -any,-    containers -any,-    mtl >= 2,-    cryptohash -any,-    network -any,-    parsec -any,-    random -any,-    random-shuffle -any,-    monad-control >= 0.3.1,-    lifted-base >= 0.1.0.3,-    transformers-base >= 0.4.1-stability: alpha-homepage: http://github.com/TonyGen/mongoDB-haskell-package-url:-bug-reports:-synopsis: Driver (client) for MongoDB, a free, scalable, fast, document DBMS-description: This package lets you connect to MongoDB servers and update/query their data. Please see the example in Database.MongoDB and the tutorial from the homepage. For information about MongoDB itself, see www.mongodb.org.-category: Database-tested-with:-data-files:-data-dir: ""-extra-source-files:-extra-tmp-files:-exposed-modules:-    Database.MongoDB-    Database.MongoDB.Admin-    Database.MongoDB.Connection-    Database.MongoDB.Internal.Protocol-    Database.MongoDB.Internal.Util-    Database.MongoDB.Query-    System.IO.Pipeline-    System.IO.Pool-exposed: True-buildable: True-build-tools:-cpp-options:-cc-options:-ld-options:-pkgconfig-depends:-frameworks:-c-sources:-extensions:-extra-libraries:-extra-lib-dirs:-includes:-install-includes:-include-dirs:-hs-source-dirs: .-other-modules:-ghc-prof-options: -auto-all-ghc-shared-options:-ghc-options: -Wall-hugs-options:-nhc98-options:-jhc-options:+Name:           mongoDB+Version:        1.3.0+Synopsis:       Driver (client) for MongoDB, a free, scalable, fast, document+                DBMS+Description:    This package lets you connect to MongoDB servers and+                update/query their data. Please see the example in+                Database.MongoDB and the tutorial from the homepage. For+                information about MongoDB itself, see www.mongodb.org.+Category:       Database+Homepage:       http://github.com/selectel/mongodb-haskell+Author:         Tony Hannan+Maintainer:     Fedor Gogolev <knsd@knsd.net>+Copyright:      Copyright (c) 2010-2012 10gen Inc.+License:        OtherLicense+License-file:   LICENSE+Cabal-version:  >= 1.2+Build-type:     Simple+Stability:      alpha++Library+  GHC-options:      -Wall+  GHC-prof-options: -auto-all++  Build-depends:      array -any+                    , base <5+                    , binary -any+                    , bson >= 0.2.0 && < 0.3.0+                    , text+                    , bytestring -any+                    , containers -any+                    , mtl >= 2+                    , cryptohash -any+                    , network -any+                    , parsec -any+                    , random -any+                    , random-shuffle -any+                    , monad-control >= 0.3.1+                    , lifted-base >= 0.1.0.3+                    , transformers-base >= 0.4.1++  Exposed-modules:  Database.MongoDB+                    Database.MongoDB.Admin+                    Database.MongoDB.Connection+                    Database.MongoDB.Internal.Protocol+                    Database.MongoDB.Internal.Util+                    Database.MongoDB.Query+                    System.IO.Pipeline+                    System.IO.Pool