Skip to content

Commit bbe3f55

Browse files
committed
remote: implement Logger_Read
Adds `setDataSource` which can be used to set a function to be polled when daemon asks for data using `Logger_Read`. Function should return `Nothing` when all data was read. `clearDataSource` should be used after the operation using the data source is finished. Related to #265
1 parent be7fda5 commit bbe3f55

File tree

3 files changed

+58
-48
lines changed

3 files changed

+58
-48
lines changed

hnix-store-remote/src/System/Nix/Store/Remote/Logger.hs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ module System.Nix.Store.Remote.Logger
33
) where
44

55
import Control.Monad.Except (throwError)
6+
import Control.Monad.IO.Class (liftIO)
67
import Data.ByteString (ByteString)
78
import Data.Serialize (Result(..))
8-
import System.Nix.Store.Remote.Serialize.Prim (putByteString)
99
import System.Nix.Store.Remote.Serializer (LoggerSError, logger, runSerialT)
10-
import System.Nix.Store.Remote.Socket (sockGet8, sockPut)
11-
import System.Nix.Store.Remote.MonadStore (MonadRemoteStore, RemoteStoreError(..), appendLog, clearData, getData, getProtoVersion, setError)
10+
import System.Nix.Store.Remote.Socket (sockGet8)
11+
import System.Nix.Store.Remote.MonadStore (MonadRemoteStore, RemoteStoreError(..), appendLog, getDataSource, getStoreSocket, getProtoVersion, setError)
1212
import System.Nix.Store.Remote.Types.Logger (Logger(..))
1313
import System.Nix.Store.Remote.Types.ProtoVersion (ProtoVersion)
1414

1515
import qualified Control.Monad
1616
import qualified Data.Serialize.Get
1717
import qualified Data.Serializer
18+
import qualified Network.Socket.ByteString
1819

1920
processOutput
2021
:: MonadRemoteStore m
@@ -55,16 +56,18 @@ processOutput = do
5556
Logger_Last -> appendLog Logger_Last
5657

5758
-- Read data from source
58-
Logger_Read _n -> do
59-
mdata <- getData
60-
case mdata of
61-
Nothing -> throwError RemoteStoreError_NoDataProvided
62-
Just part -> do
63-
-- XXX: we should check/assert part size against n of (Read n)
64-
-- ^ not really, this is just an indicator how big of a chunk
65-
-- to read from the source
66-
sockPut $ putByteString part
67-
clearData
59+
Logger_Read size -> do
60+
mSource <- getDataSource
61+
case mSource of
62+
Nothing ->
63+
throwError RemoteStoreError_NoDataSourceProvided
64+
Just source -> do
65+
mChunk <- liftIO $ source size
66+
case mChunk of
67+
Nothing -> throwError RemoteStoreError_DataSourceExhausted
68+
Just chunk -> do
69+
sock <- getStoreSocket
70+
liftIO $ Network.Socket.ByteString.sendAll sock chunk
6871

6972
loop
7073

hnix-store-remote/src/System/Nix/Store/Remote/MonadStore.hs

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ import System.Nix.Store.Remote.Types.StoreConfig (HasStoreSocket(..), StoreConfi
3636
data RemoteStoreState = RemoteStoreState {
3737
remoteStoreState_logs :: [Logger]
3838
, remoteStoreState_gotError :: Bool
39-
, remoteStoreState_mData :: Maybe ByteString
39+
, remoteStoreState_mDataSource :: Maybe (Word64 -> IO (Maybe ByteString))
40+
-- ^ Source for @Logger_Read@, this will be called repeatedly
41+
-- as the daemon requests chunks of size @Word64@.
42+
-- If the function returns Nothing and daemon tries to read more
43+
-- data an error is thrown.
4044
, remoteStoreState_mNarSource :: Maybe (NarSource IO)
4145
}
4246

@@ -55,7 +59,8 @@ data RemoteStoreError
5559
| RemoteStoreError_IOException SomeException
5660
| RemoteStoreError_LoggerLeftovers String ByteString -- when there are bytes left over after incremental logger parser is done, (Done x leftover), first param is show x
5761
| RemoteStoreError_LoggerParserFail String ByteString -- when incremental parser returns ((Fail msg leftover) :: Result)
58-
| RemoteStoreError_NoDataProvided
62+
| RemoteStoreError_NoDataSourceProvided -- remoteStoreState_mDataSource is required but it is Nothing
63+
| RemoteStoreError_DataSourceExhausted -- remoteStoreState_mDataSource returned Nothing but more data was requested
5964
| RemoteStoreError_NoNarSourceProvided
6065
| RemoteStoreError_OperationFailed
6166
| RemoteStoreError_ProtocolMismatch
@@ -122,7 +127,7 @@ runRemoteStoreT r =
122127
emptyState = RemoteStoreState
123128
{ remoteStoreState_logs = mempty
124129
, remoteStoreState_gotError = False
125-
, remoteStoreState_mData = Nothing
130+
, remoteStoreState_mDataSource = Nothing
126131
, remoteStoreState_mNarSource = Nothing
127132
}
128133

@@ -182,34 +187,6 @@ class ( MonadIO m
182187
=> m Bool
183188
gotError = lift gotError
184189

185-
setData :: ByteString -> m ()
186-
default setData
187-
:: ( MonadTrans t
188-
, MonadRemoteStoreR r m'
189-
, m ~ t m'
190-
)
191-
=> ByteString
192-
-> m ()
193-
setData = lift . setData
194-
195-
getData :: m (Maybe ByteString)
196-
default getData
197-
:: ( MonadTrans t
198-
, MonadRemoteStoreR r m'
199-
, m ~ t m'
200-
)
201-
=> m (Maybe ByteString)
202-
getData = lift getData
203-
204-
clearData :: m ()
205-
default clearData
206-
:: ( MonadTrans t
207-
, MonadRemoteStoreR r m'
208-
, m ~ t m'
209-
)
210-
=> m ()
211-
clearData = lift clearData
212-
213190
getStoreDir :: m StoreDir
214191
default getStoreDir
215192
:: ( MonadTrans t
@@ -247,6 +224,36 @@ class ( MonadIO m
247224
=> m (Maybe (NarSource IO))
248225
takeNarSource = lift takeNarSource
249226

227+
setDataSource :: (Word64 -> IO (Maybe ByteString)) -> m ()
228+
default setDataSource
229+
:: ( MonadTrans t
230+
, MonadRemoteStoreR r m'
231+
, m ~ t m'
232+
)
233+
=> (Word64 -> IO (Maybe ByteString))
234+
-> m ()
235+
setDataSource x = lift (setDataSource x)
236+
237+
getDataSource :: m (Maybe (Word64 -> IO (Maybe ByteString)))
238+
default getDataSource
239+
:: ( MonadTrans t
240+
, MonadRemoteStoreR r m'
241+
, m ~ t m'
242+
)
243+
=> m (Maybe (Word64 -> IO (Maybe ByteString)))
244+
getDataSource = lift getDataSource
245+
246+
clearDataSource :: m ()
247+
default clearDataSource
248+
:: ( MonadTrans t
249+
, MonadRemoteStoreR r m'
250+
, m ~ t m'
251+
)
252+
=> m ()
253+
clearDataSource = lift clearDataSource
254+
255+
256+
250257
instance MonadRemoteStoreR r m => MonadRemoteStoreR r (StateT s m)
251258
instance MonadRemoteStoreR r m => MonadRemoteStoreR r (ReaderT r m)
252259
instance MonadRemoteStoreR r m => MonadRemoteStoreR r (ExceptT RemoteStoreError m)
@@ -271,9 +278,9 @@ instance ( MonadIO m
271278
clearError = RemoteStoreT $ modify $ \s -> s { remoteStoreState_gotError = False }
272279
gotError = remoteStoreState_gotError <$> RemoteStoreT get
273280

274-
getData = remoteStoreState_mData <$> RemoteStoreT get
275-
setData x = RemoteStoreT $ modify $ \s -> s { remoteStoreState_mData = pure x }
276-
clearData = RemoteStoreT $ modify $ \s -> s { remoteStoreState_mData = Nothing }
281+
setDataSource x = RemoteStoreT $ modify $ \s -> s { remoteStoreState_mDataSource = pure x }
282+
getDataSource = remoteStoreState_mDataSource <$> RemoteStoreT get
283+
clearDataSource = RemoteStoreT $ modify $ \s -> s { remoteStoreState_mDataSource = Nothing }
277284

278285
setNarSource x = RemoteStoreT $ modify $ \s -> s { remoteStoreState_mNarSource = pure x }
279286
takeNarSource = RemoteStoreT $ do

hnix-store-remote/src/System/Nix/Store/Remote/Types/Logger.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ word64ToLoggerOpCode = \case
8181

8282
data Logger
8383
= Logger_Next Text
84-
| Logger_Read Int -- data needed from source
84+
| Logger_Read Word64 -- data needed from source
8585
| Logger_Write ByteString -- data for sink
8686
| Logger_Last
8787
| Logger_Error (Either BasicError ErrorInfo)

0 commit comments

Comments
 (0)