3
3
{-# LANGUAGE FlexibleContexts #-}
4
4
{-# LANGUAGE OverloadedStrings #-}
5
5
{-# LANGUAGE ScopedTypeVariables #-}
6
- {-# LANGUAGE TupleSections #-}
7
6
{-# LANGUAGE TypeApplications #-}
8
7
{-# LANGUAGE ViewPatterns #-}
9
8
@@ -12,17 +11,9 @@ module Main (main) where
12
11
import Cardano.Crypto.Init (cryptoInit )
13
12
import Cardano.Tools.DBAnalyser.HasAnalysis (Args , mkProtocolInfo )
14
13
import Codec.Serialise
15
- import qualified Control.Monad as Monad
16
14
import Control.Monad.Except
17
- import qualified Control.Monad.Trans as Trans (lift )
18
- import Control.ResourceRegistry (ResourceRegistry )
19
- import qualified Control.ResourceRegistry as RR
20
- import Control.Tracer (nullTracer )
21
15
import DBAnalyser.Parsers
22
16
import Data.Bifunctor
23
- import qualified Data.ByteString.Builder as BS
24
- import qualified Data.SOP.Dict as Dict
25
- import qualified Debug.Trace as Debug
26
17
import Main.Utf8
27
18
import Options.Applicative
28
19
import Ouroboros.Consensus.Block
@@ -31,34 +22,17 @@ import Ouroboros.Consensus.Cardano.StreamingLedgerTables
31
22
import Ouroboros.Consensus.Config
32
23
import Ouroboros.Consensus.Ledger.Basics
33
24
import Ouroboros.Consensus.Ledger.Extended
34
- import Ouroboros.Consensus.Ledger.SupportsProtocol
35
- import Ouroboros.Consensus.Ledger.Tables.Utils
36
25
import Ouroboros.Consensus.Node.ProtocolInfo
37
- import Ouroboros.Consensus.Storage.LedgerDB
38
26
import Ouroboros.Consensus.Storage.LedgerDB.Snapshots
39
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.Args as V1
40
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.BackingStore as V1
41
27
import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.BackingStore.Impl.LMDB as V1
42
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.DbChangelog as V1
43
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.Lock as V1
44
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V1.Snapshots as V1
45
- import Ouroboros.Consensus.Storage.LedgerDB.V2.Args
46
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.InMemory as InMemory
47
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.InMemory as V2
48
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.LSM as LSM
49
- import qualified Ouroboros.Consensus.Storage.LedgerDB.V2.LedgerSeq as V2
50
- import Ouroboros.Consensus.Util.CRC
51
28
import Ouroboros.Consensus.Util.IOLike
52
29
import Ouroboros.Consensus.Util.StreamingLedgerTables
53
- import qualified System.Directory as Directory
30
+ import qualified System.Directory as D
54
31
import System.FS.API
55
- import System.FS.API.Lazy
56
32
import System.FS.CRC
57
33
import System.FS.IO
58
- import System.FilePath (splitFileName )
59
- import System.IO (hFlush , stdout )
60
- import System.IO.Temp
61
- import System.Random
34
+ import System.FilePath (splitDirectories )
35
+ import qualified System.FilePath as F
62
36
63
37
data Format
64
38
= Mem FilePath
@@ -127,10 +101,18 @@ parsePath optName strHelp =
127
101
128
102
-- Helpers
129
103
130
- pathToDiskSnapshot :: FilePath -> Maybe (SomeHasFS IO , FsPath , DiskSnapshot )
131
- pathToDiskSnapshot path = (SomeHasFS $ ioHasFS $ MountPoint dir,mkFsPath [file],) <$> snapshotFromPath file
132
- where
133
- (dir, file) = splitFileName path
104
+ -- | Given a filepath pointing to a snapshot (with or without a trailing slash), produce:
105
+ --
106
+ -- * A HasFS at the snapshot directory
107
+ pathToHasFS :: FilePath -> SomeHasFS IO
108
+ pathToHasFS (maybeRemoveTrailingSlash -> path) =
109
+ SomeHasFS $ ioHasFS $ MountPoint path
110
+
111
+ maybeRemoveTrailingSlash :: String -> String
112
+ maybeRemoveTrailingSlash s = case last s of
113
+ ' /' -> init s
114
+ ' \\ ' -> init s
115
+ _ -> s
134
116
135
117
defaultLMDBLimits :: V1. LMDBLimits
136
118
defaultLMDBLimits =
@@ -142,166 +124,15 @@ defaultLMDBLimits =
142
124
143
125
data Error blk
144
126
= SnapshotError (SnapshotFailure blk )
145
- | TablesCantDeserializeError DeserialiseFailure
146
- | TablesTrailingBytes
147
- | SnapshotFormatMismatch Format String
148
127
| ReadSnapshotCRCError FsPath CRCError
149
128
deriving Exception
150
129
151
130
instance StandardHash blk => Show (Error blk ) where
152
131
show (SnapshotError err) =
153
132
" Couldn't deserialize the snapshot. Are you running the same node version that created the snapshot? "
154
133
<> show err
155
- show (TablesCantDeserializeError err) = " Couldn't deserialize the tables: " <> show err
156
- show TablesTrailingBytes = " Malformed tables, there are trailing bytes!"
157
- show (SnapshotFormatMismatch expected err) =
158
- " The input snapshot does not seem to correspond to the input format:\n\t "
159
- <> show expected
160
- <> " \n\t The provided path "
161
- <> err
162
134
show (ReadSnapshotCRCError fp err) = " An error occurred while reading the snapshot checksum at " <> show fp <> " : \n\t " <> show err
163
135
164
- -- load ::
165
- -- forall blk.
166
- -- ( CanStowLedgerTables (LedgerState blk)
167
- -- , LedgerSupportsProtocol blk
168
- -- , LedgerSupportsLedgerDB blk
169
- -- ) =>
170
- -- Config ->
171
- -- ResourceRegistry IO ->
172
- -- CodecConfig blk ->
173
- -- FilePath ->
174
- -- ExceptT (Error blk) IO (ExtLedgerState blk EmptyMK, LedgerTables (ExtLedgerState blk) ValuesMK)
175
- -- load config rr ccfg tempFP =
176
- -- case from config of
177
- -- -- Legacy (pathToDiskSnapshot -> Just (fs@(SomeHasFS hasFS), path, _)) -> do
178
- -- -- (st, checksumAsRead) <-
179
- -- -- first unstowLedgerTables
180
- -- -- <$> withExceptT
181
- -- -- (SnapshotError . InitFailureRead . ReadSnapshotFailed)
182
- -- -- (readExtLedgerState fs (decodeDiskExtLedgerState ccfg) decode path)
183
- -- -- let crcPath = path <.> "checksum"
184
- -- -- crcFileExists <- Trans.lift $ doesFileExist hasFS crcPath
185
- -- -- Monad.when crcFileExists $ do
186
- -- -- snapshotCRC <-
187
- -- -- withExceptT (ReadSnapshotCRCError crcPath) $
188
- -- -- readCRC hasFS crcPath
189
- -- -- Monad.when (checksumAsRead /= snapshotCRC) $
190
- -- -- throwError $
191
- -- -- SnapshotError $
192
- -- -- InitFailureRead ReadSnapshotDataCorruption
193
- -- -- pure (forgetLedgerTables st, projectLedgerTables st)
194
- -- Mem (pathToDiskSnapshot -> Just (fs, path, ds)) -> do
195
- -- (ls, _) <- withExceptT SnapshotError $ V2.loadSnapshot nullTracer rr ccfg fs ds
196
- -- let h = V2.currentHandle ls
197
- -- (V2.state h,) <$> Trans.lift (V2.readAll (V2.tables h) (V2.state h))
198
- -- LMDB (pathToDiskSnapshot -> Just (fs, _, ds)) -> do
199
- -- ((dbch, k, bstore), _) <-
200
- -- withExceptT SnapshotError $
201
- -- V1.loadSnapshot
202
- -- nullTracer
203
- -- (V1.LMDBBackingStoreArgs tempFP defaultLMDBLimits Dict.Dict)
204
- -- ccfg
205
- -- (V1.SnapshotsFS fs)
206
- -- rr
207
- -- ds
208
- -- values <- Trans.lift (V1.bsReadAll bstore (V1.changelogLastFlushedState dbch))
209
- -- _ <- Trans.lift $ RR.release k
210
- -- pure (V1.current dbch, values)
211
- -- LSM _ _ -> error "unimplemented"
212
- -- _ -> error "Malformed input path!"
213
-
214
- -- store ::
215
- -- ( CanStowLedgerTables (LedgerState blk)
216
- -- , LedgerSupportsProtocol blk
217
- -- , LedgerSupportsLedgerDB blk
218
- -- ) =>
219
- -- Config ->
220
- -- CodecConfig blk ->
221
- -- (ExtLedgerState blk EmptyMK, LedgerTables (ExtLedgerState blk) ValuesMK) ->
222
- -- SomeHasFS IO ->
223
- -- IO ()
224
- -- store config ccfg (state, tbs) tempFS =
225
- -- case to config of
226
- -- -- Legacy (p@(pathToDiskSnapshot -> Just (fs@(SomeHasFS hasFS), path, _))) -> do
227
- -- -- crc <-
228
- -- -- writeExtLedgerState
229
- -- -- fs
230
- -- -- (encodeDiskExtLedgerState ccfg)
231
- -- -- path
232
- -- -- (stowLedgerTables $ state `withLedgerTables` tbs)
233
- -- -- withFile hasFS (path <.> "checksum") (WriteMode MustBeNew) $ \h ->
234
- -- -- Monad.void $ hPutAll hasFS h . BS.toLazyByteString . BS.word32HexFixed $ getCRC crc
235
- -- -- putStrLn "DONE"
236
- -- -- putStrLn $
237
- -- -- unlines $
238
- -- -- [ "You can now copy the file "
239
- -- -- ++ p
240
- -- -- ++ " to your `ledger` directory in your ChainDB storage."
241
- -- -- , "Note this snapshot can only be used by cardano-node <10.4."
242
- -- -- ]
243
- -- Mem (p@(pathToDiskSnapshot -> Just (fs, _, DiskSnapshot _ suffix))) -> do
244
- -- lseq <- V2.empty state tbs $ V2.newInMemoryLedgerTablesHandle nullTracer fs
245
- -- let h = V2.currentHandle lseq
246
- -- Monad.void $ InMemory.implTakeSnapshot ccfg nullTracer fs suffix h
247
- -- putStrLn "DONE"
248
- -- putStrLn $
249
- -- unlines $
250
- -- [ "You can now copy the directory "
251
- -- ++ p
252
- -- ++ " to your `ledger` directory in your ChainDB storage."
253
- -- , "Note this snapshot can only be used by cardano-node >=10.4 configured to use the InMemory backend (set the \"LedgerDB\".\"Backend\" key in your config file to \"V2InMemory\" or leave it undefined)."
254
- -- ]
255
- -- LMDB (p@(pathToDiskSnapshot -> Just (fs, _, DiskSnapshot _ suffix))) -> do
256
- -- chlog <- newTVarIO (V1.empty state)
257
- -- lock <- V1.mkLedgerDBLock
258
- -- bs <-
259
- -- V1.newLMDBBackingStore
260
- -- nullTracer
261
- -- defaultLMDBLimits
262
- -- (V1.LiveLMDBFS tempFS)
263
- -- (V1.SnapshotsFS fs)
264
- -- (V1.InitFromValues (pointSlot $ getTip state) state tbs)
265
- -- Monad.void $ V1.withReadLock lock $ do
266
- -- V1.implTakeSnapshot chlog ccfg nullTracer (V1.SnapshotsFS fs) bs suffix
267
- -- putStrLn "DONE"
268
- -- putStrLn $
269
- -- unlines $
270
- -- [ "You can now copy the directory "
271
- -- ++ p
272
- -- ++ " to your `ledger` directory in your ChainDB storage."
273
- -- , "Note this snapshot can only be used by cardano-node >=10.4 configured to use the LMDB backend (set the \"LedgerDB\".\"Backend\" key in your config file to \"V1LMDB\")."
274
- -- ]
275
- -- LSM (p@(pathToDiskSnapshot -> Just (fs, _, DiskSnapshot _ suffix))) dbPath -> do
276
- -- exists <- Directory.doesDirectoryExist dbPath
277
- -- Monad.when (not exists) $ Directory.createDirectory dbPath
278
- -- RR.withRegistry $ \reg -> do
279
- -- (_, SomeHasFSAndBlockIO hasFS blockIO) <- LSM.stdMkBlockIOFS dbPath reg
280
- -- salt <- fst . genWord64 <$> newStdGen
281
- -- LSM.withNewSession nullTracer hasFS blockIO salt (mkFsPath [""]) $ \session -> do
282
- -- lsmTable <- LSM.tableFromValuesMK reg session state tbs
283
- -- lsmHandle <- LSM.newLSMLedgerTablesHandle nullTracer reg lsmTable
284
- -- Monad.void $
285
- -- LSM.implTakeSnapshot
286
- -- ccfg
287
- -- nullTracer
288
- -- fs
289
- -- suffix
290
- -- (V2.StateRef state lsmHandle)
291
- -- putStrLn "DONE"
292
- -- putStrLn $
293
- -- unlines $
294
- -- [ "You can now:"
295
- -- , "- copy the directory "
296
- -- ++ p
297
- -- ++ " to your `ledger` directory in your ChainDB storage."
298
- -- , "- copy the directory "
299
- -- ++ dbPath
300
- -- ++ " to your fast storage device and point to it in your config file."
301
- -- , "Note this snapshot can only be used by cardano-node >=10.7 configured to use the LSM backend (set the \"LedgerDB\".\"Backend\" key in your config file to \"V2LSM\")."
302
- -- ]
303
- -- _ -> error "Malformed output path!"
304
-
305
136
main :: IO ()
306
137
main = withStdTerminalHandles $ do
307
138
cryptoInit
@@ -318,32 +149,24 @@ main = withStdTerminalHandles $ do
318
149
(pure . first ledgerState)
319
150
=<< runExceptT (readExtLedgerState fs (decodeDiskExtLedgerState ccfg) decode path)
320
151
321
- (st, f) <- case from conf of
322
- Mem fp@ (pathToDiskSnapshot -> Just (fs, path, _)) -> do
323
- (st, _) <- getState fs path
324
- pure (st, fromInMemory fp)
325
- LMDB fp@ (pathToDiskSnapshot -> Just (fs, path, _)) -> do
326
- (st, _) <- getState (Debug. trace (show fp) fs) (Debug. traceShowId path </> mkFsPath [" state" ])
327
- pure (st, fromLMDB (fp <> " /tables" ))
328
- LSM fp@ (pathToDiskSnapshot -> Just (fs, path, ds)) fp2 -> do
329
- (st, _) <- getState fs (Debug. traceShowId path </> mkFsPath [" state" ])
330
- pure (st, fromLSM fp2 (dsSuffix ds))
331
- let t = case to conf of
332
- Mem fp@ (pathToDiskSnapshot -> Just (fs, path, _)) ->
333
- toInMemory fp
334
- LMDB fp@ (pathToDiskSnapshot -> Just (fs, path, _)) ->
335
- toLMDB fp
336
- LSM fp@ (pathToDiskSnapshot -> Just (fs, path, _)) fp2 ->
337
- toLSM fp
338
- either throwIO pure =<< runExceptT (stream st f t)
152
+ (st, fpInDir, f) <- case from conf of
153
+ Mem fp@ (pathToHasFS -> fs) -> do
154
+ (st, _) <- getState fs (mkFsPath [" state" ])
155
+ pure (st, fp, fromInMemory (fp F. </> " tables" F. </> " tvar" ))
156
+ LMDB fp@ (pathToHasFS -> fs) -> do
157
+ (st, _) <- getState fs (mkFsPath [" state" ])
158
+ pure (st, fp, fromLMDB (fp F. </> " tables" ) defaultLMDBLimits)
159
+ LSM fp@ (pathToHasFS -> fs) lsmDbPath -> do
160
+ (st, _) <- getState fs (mkFsPath [" state" ])
161
+ pure (st, fp, fromLSM lsmDbPath (last $ splitDirectories fp))
339
162
340
- -- withSystemTempDirectory "lmdb" $ \dir -> do
341
- -- let tempFS = SomeHasFS $ ioHasFS $ MountPoint dir
342
- -- RR.withRegistry $ \rr -> do
343
- -- putStr "Loading snapshot..."
344
- -- hFlush stdout
345
- -- state <- either throwIO pure =<< runExceptT (load conf rr ccfg dir)
346
- -- putStrLn "DONE"
347
- -- putStr "Writing snapshot..."
348
- -- hFlush stdout
349
- -- store conf ccfg state tempFS
163
+ let (fpOutDir, t) = case to conf of
164
+ Mem fp -> (fp, toInMemory fp)
165
+ LMDB fp -> (fp, toLMDB fp defaultLMDBLimits)
166
+ LSM fp lsmDbPath -> (fp, toLSM lsmDbPath ( last $ splitDirectories fp))
167
+
168
+ D. createDirectoryIfMissing True fpOutDir
169
+
170
+ D. copyFile (fpInDir F. </> " state " ) (fpOutDir F. </> " state " )
171
+
172
+ either throwIO pure =<< runExceptT (stream st f t)
0 commit comments