{-# LANGUAGE DataKinds #-}
module TahoeLAFS.Storage.Backend (
Backend (..),
WriteImmutableError (..),
writeMutableShare,
withUploadSecret,
) where
import Control.Exception (
Exception,
throw,
throwIO,
)
import Data.Map.Strict (
fromList,
)
import Network.HTTP.Types (
ByteRanges,
)
import TahoeLAFS.Storage.API (
AllocateBuckets,
AllocationResult,
CBORSet (..),
CorruptionDetails,
LeaseSecret (..),
QueryRange,
ReadTestWriteResult (..),
ReadTestWriteVectors (..),
ShareData,
ShareNumber,
StorageIndex,
TestWriteVectors (..),
UploadSecret (..),
Version,
WriteEnablerSecret,
WriteVector (..),
isUploadSecret,
)
data WriteImmutableError
= MissingUploadSecret
| ShareSizeMismatch
| ImmutableShareAlreadyWritten
| ShareNotAllocated
| IncorrectUploadSecret
| IncorrectWriteEnablerSecret
deriving (Ord, Eq, Show)
instance Exception WriteImmutableError
class Backend b where
version :: b -> IO Version
-- | Update the lease expiration time on the shares associated with the
-- given storage index.
renewLease :: b -> StorageIndex -> [LeaseSecret] -> IO ()
createImmutableStorageIndex :: b -> StorageIndex -> Maybe [LeaseSecret] -> AllocateBuckets -> IO AllocationResult
-- May throw ImmutableShareAlreadyWritten
writeImmutableShare :: b -> StorageIndex -> ShareNumber -> Maybe [LeaseSecret] -> ShareData -> Maybe ByteRanges -> IO ()
abortImmutableUpload :: b -> StorageIndex -> ShareNumber -> Maybe [LeaseSecret] -> IO ()
adviseCorruptImmutableShare :: b -> StorageIndex -> ShareNumber -> CorruptionDetails -> IO ()
getImmutableShareNumbers :: b -> StorageIndex -> IO (CBORSet ShareNumber)
readImmutableShare :: b -> StorageIndex -> ShareNumber -> QueryRange -> IO ShareData
-- | Read some ranges of all shares held and/or, if test conditions are
-- met, overwrite some ranges of some shares.
readvAndTestvAndWritev ::
b ->
-- | The storage index at which to operate.
StorageIndex ->
-- | A shared secret which the backend can use to authorize the writes.
WriteEnablerSecret ->
-- | The reads, tests, and writes to perform.
ReadTestWriteVectors ->
IO ReadTestWriteResult
readMutableShare :: b -> StorageIndex -> ShareNumber -> QueryRange -> IO ShareData
getMutableShareNumbers :: b -> StorageIndex -> IO (CBORSet ShareNumber)
adviseCorruptMutableShare :: b -> StorageIndex -> ShareNumber -> CorruptionDetails -> IO ()
writeMutableShare ::
Backend b =>
b ->
StorageIndex ->
ShareNumber ->
WriteEnablerSecret ->
ShareData ->
Maybe ByteRanges ->
IO ()
writeMutableShare b storageIndex shareNumber writeEnablerSecret shareData Nothing = do
let testWriteVectors =
fromList
[
( shareNumber
, TestWriteVectors
{ test = []
, write =
[ WriteVector
{ writeOffset = 0
, shareData = shareData
}
]
, newLength = Nothing -- XXX expose this?
}
)
]
let vectors =
ReadTestWriteVectors
{ testWriteVectors = testWriteVectors
, readVector = mempty
}
result <- readvAndTestvAndWritev b storageIndex writeEnablerSecret vectors
if success result
then return ()
else throw WriteRefused
writeMutableShare _ _ _ _ _ _ = error "writeMutableShare got bad input"
data WriteRefused = WriteRefused deriving (Show, Eq)
instance Exception WriteRefused
withUploadSecret :: Maybe [LeaseSecret] -> (UploadSecret -> IO a) -> IO a
withUploadSecret ss f =
case filter isUploadSecret <$> ss of
Just [Upload s] -> f s
_ -> throwIO MissingUploadSecret