packages feed

vcache 0.2.1 → 0.2.2

raw patch · 3 files changed

+64/−12 lines, 3 files

Files

hsrc_lib/Database/VCache/Read.hs view
@@ -2,12 +2,14 @@ module Database.VCache.Read     ( readAddrIO     , readRefctIO+    , withBytesIO     ) where  import Control.Monad import qualified Data.Map.Strict as Map import qualified Data.List as L import Control.Concurrent.MVar+import Data.Word import Foreign.Ptr import Foreign.Storable import Foreign.Marshal.Alloc@@ -23,7 +25,11 @@ -- cache weight, or fails. This first tries reading the database, then -- falls back to reading from recent allocation frames.  readAddrIO :: VSpace -> Address -> VGet a -> IO (a, Int)-readAddrIO vc addr parser = +readAddrIO vc addr = withAddrValIO vc addr . readVal vc+{-# INLINE readAddrIO #-}++withAddrValIO :: VSpace -> Address -> (MDB_val -> IO a) -> IO a+withAddrValIO vc addr action =      alloca $ \ pAddr ->     poke pAddr addr >>     let vAddr = MDB_val { mv_data = castPtr pAddr@@ -31,18 +37,17 @@                         }     in     withRdOnlyTxn vc $ \ txn -> -    let db = vcache_db_memory vc in-    let rd = readVal vc parser in-    mdb_get' txn db vAddr >>= \ mbData ->+    mdb_get' txn (vcache_db_memory vc) vAddr >>= \ mbData ->     case mbData of-        Just vData -> rd vData -- found data in database (ideal)+        Just vData -> action vData -- found data in database (ideal)         Nothing -> -- since not in the database, try the allocator             let ff = Map.lookup addr . alloc_list in             readMVar (vcache_memory vc) >>= \ memory ->             let ac = mem_alloc memory in             case allocFrameSearch ff ac of-                Just an -> withByteStringVal (alloc_data an) rd -- found data in allocator+                Just an -> withByteStringVal (alloc_data an) action -- found data in allocator                 Nothing -> fail $ "VCache: address " ++ show addr ++ " is undefined!"+{-# NOINLINE withAddrValIO #-}  readVal :: VSpace -> VGet a -> MDB_val -> IO (a, Int) readVal vc p v = _vget (vgetFull p) s0 >>= retv where@@ -88,5 +93,14 @@     in     mdb_get' txn (vcache_db_refcts vc) vAddr >>= \ mbData ->     maybe (return 0) readRefctBytes mbData++-- | Zero-copy access to raw bytes for an address.+withBytesIO :: VSpace -> Address -> (Ptr Word8 -> Int -> IO a) -> IO a+withBytesIO vc addr action = +    withAddrValIO vc addr $ \ v -> +    action (mv_data v) (fromIntegral (mv_size v))+{-# INLINE withBytesIO #-}++  
hsrc_lib/Database/VCache/VRef.hs view
@@ -1,4 +1,4 @@-+{-# LANGUAGE BangPatterns #-}  module Database.VCache.VRef     ( VRef@@ -9,11 +9,21 @@     , vref_space     , CacheMode(..)     , vrefc, derefc++    , withVRefBytes+    , unsafeVRefEncoding+     ) where  import Control.Monad import Data.IORef+import Data.Bits+import Data.Word+import Data.ByteString (ByteString)+import Foreign.Ptr+import Foreign.Storable import System.IO.Unsafe + import Database.VCache.Types import Database.VCache.Alloc import Database.VCache.Read@@ -69,10 +79,6 @@             (c', c' `seq` op) {-# NOINLINE derefc #-} ---- I've modified how VRefs are recorded -- -- | Dereference a VRef. This will read from the cache if the value -- is available, but will not update the cache. If the value is not -- cached, it will be read instead from the persistence layer.@@ -87,6 +93,38 @@         Cached r _ -> return r         NotCached -> liftM fst (readVRef v) {-# INLINABLE deref' #-}++-- | Specialized, zero-copy access to a `VRef ByteString`. Access to +-- the given ByteString becomes invalid after returning. This operation+-- may also block the writer if it runs much longer than a single+-- writer batch (though, writer batches are frequently large enough +-- that this shouldn't be a problem if you're careful).+--+withVRefBytes :: VRef ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a+withVRefBytes v action = unsafeVRefEncoding v $ \ p n ->+    -- valid ByteString encoding: varNat, bytes, 0 (children)+    readVarNat p 0 >>= \ (p', n') ->+    let bOK = (p' `plusPtr` n') == (p `plusPtr` (n-1)) in+    let eMsg = show v ++ " doesn't contain a ByteString" in+    unless bOK (fail $ "withVRefBytes: " ++ eMsg) >>+    action p' n'++readVarNat :: Ptr Word8 -> Int -> IO (Ptr Word8, Int)+readVarNat !p !n =+    peek p >>= \ w8 ->+    let p' = p `plusPtr` 1 in+    let n' = (n `shiftL` 7) + (fromIntegral $ w8 .&. 0x7f) in+    let bDone = (0 == (w8 .&. 0x80)) in+    if bDone then return (p', n') else+    readVarNat p' n'+    +-- | Zero-copy access to the raw encoding for any VRef. The given data+-- becomes invalid after returning. This is provided for mostly for+-- debugging purposes, i.e. so you can peek under the hood and see how+-- things are encoded or eyeball the encoding. +unsafeVRefEncoding :: VRef any -> (Ptr Word8 -> Int -> IO a) -> IO a+unsafeVRefEncoding v = withBytesIO (vref_space v) (vref_addr v)+{-# INLINE unsafeVRefEncoding #-}  -- | Each VRef has an numeric address in the VSpace. This address is -- non-deterministic, and essentially independent of the arguments to
vcache.cabal view
@@ -1,5 +1,5 @@ Name: vcache-Version: 0.2.1+Version: 0.2.2 Synopsis: large, persistent, memcached values and structure sharing for Haskell  Category: Database Description: