@@ -431,8 +431,10 @@ openSession tr hfs hbio dir = do
431431 -- is automatically released by bracketOnError.
432432 checkTopLevelDirLayout
433433
434- FS. removeDirectoryRecursive hfs activeDirPath -- TODO: exceptions safety
435- FS. createDirectory hfs activeDirPath
434+ -- Clear the active directory by removing the directory and recreating
435+ -- it again.
436+ FS. removeDirectoryRecursive hfs activeDirPath
437+ `finally` FS. createDirectoryIfMissing hfs False activeDirPath
436438
437439 checkActiveDirLayout
438440 checkSnapshotsDirLayout
@@ -1064,55 +1066,58 @@ createSnapshot ::
10641066createSnapshot resolve snap label tableType t = do
10651067 traceWith (tableTracer t) $ TraceSnapshot snap
10661068 let conf = tableConfig t
1067- withOpenTable t $ \ thEnv -> do
1068- let hfs = tableHasFS thEnv
1069-
1070- -- Guard that the snapshot does not exist already
1071- let snapDir = Paths. namedSnapshotDir (tableSessionRoot thEnv) snap
1072- doesSnapshotExist <-
1073- FS. doesDirectoryExist (tableHasFS thEnv) (Paths. getNamedSnapshotDir snapDir)
1074- if doesSnapshotExist then
1075- throwIO (ErrSnapshotExists snap)
1076- else
1077- -- we assume the snapshots directory already exists, so we just have to
1078- -- create the directory for this specific snapshot.
1079- FS. createDirectory hfs (Paths. getNamedSnapshotDir snapDir)
1080-
1081- -- For the temporary implementation it is okay to just flush the buffer
1082- -- before taking the snapshot.
1083- content <- modifyWithTempRegistry
1084- (RW. unsafeAcquireWriteAccess (tableContent thEnv))
1085- (atomically . RW. unsafeReleaseWriteAccess (tableContent thEnv))
1086- $ \ reg content -> do
1087- -- TODO: When we flush the buffer here, it might be underfull, which
1088- -- could mess up the scheduling. The conservative approach is to supply
1089- -- credits as if the buffer was full, and then flush the (possibly)
1090- -- underfull buffer. However, note that this bit of code
1091- -- here is probably going to change anyway because of #392
1092- supplyCredits conf (Credit $ unNumEntries $ case confWriteBufferAlloc conf of AllocNumEntries x -> x) (tableLevels content)
1093- content' <- flushWriteBuffer
1094- (TraceMerge `contramap` tableTracer t)
1095- conf
1096- resolve
1097- hfs
1098- (tableHasBlockIO thEnv)
1099- (tableSessionRoot thEnv)
1100- (tableSessionUniqCounter thEnv)
1101- reg
1102- content
1103- pure (content', content')
1104- -- At this point, we've flushed the write buffer but we haven't created the
1105- -- snapshot file yet. If an asynchronous exception happens beyond this
1106- -- point, we'll take that loss, as the inner state of the table is still
1107- -- consistent.
1108-
1109- snappedLevels <- snapLevels (tableLevels content)
1110- snappedLevels' <- snapshotRuns snapDir snappedLevels
1111-
1112- let snapMetaData = SnapshotMetaData label tableType (tableConfig t) snappedLevels'
1113- SnapshotMetaDataFile contentPath = Paths. snapshotMetaDataFile snapDir
1114- SnapshotMetaDataChecksumFile checksumPath = Paths. snapshotMetaDataChecksumFile snapDir
1115- writeFileSnapshotMetaData hfs contentPath checksumPath snapMetaData
1069+ withOpenTable t $ \ thEnv ->
1070+ withTempRegistry $ \ reg -> do -- TODO: use the temp registry for all side effects
1071+ let hfs = tableHasFS thEnv
1072+
1073+ -- Guard that the snapshot does not exist already
1074+ let snapDir = Paths. namedSnapshotDir (tableSessionRoot thEnv) snap
1075+ doesSnapshotExist <-
1076+ FS. doesDirectoryExist (tableHasFS thEnv) (Paths. getNamedSnapshotDir snapDir)
1077+ if doesSnapshotExist then
1078+ throwIO (ErrSnapshotExists snap)
1079+ else
1080+ -- we assume the snapshots directory already exists, so we just have to
1081+ -- create the directory for this specific snapshot.
1082+ FS. createDirectory hfs (Paths. getNamedSnapshotDir snapDir)
1083+
1084+ -- For the temporary implementation it is okay to just flush the buffer
1085+ -- before taking the snapshot.
1086+ content <- modifyWithTempRegistry
1087+ (RW. unsafeAcquireWriteAccess (tableContent thEnv))
1088+ (atomically . RW. unsafeReleaseWriteAccess (tableContent thEnv))
1089+ $ \ innerReg content -> do
1090+ -- TODO: When we flush the buffer here, it might be underfull, which
1091+ -- could mess up the scheduling. The conservative approach is to supply
1092+ -- credits as if the buffer was full, and then flush the (possibly)
1093+ -- underfull buffer. However, note that this bit of code
1094+ -- here is probably going to change anyway because of #392
1095+ supplyCredits conf (Credit $ unNumEntries $ case confWriteBufferAlloc conf of AllocNumEntries x -> x) (tableLevels content)
1096+ content' <- flushWriteBuffer
1097+ (TraceMerge `contramap` tableTracer t)
1098+ conf
1099+ resolve
1100+ hfs
1101+ (tableHasBlockIO thEnv)
1102+ (tableSessionRoot thEnv)
1103+ (tableSessionUniqCounter thEnv)
1104+ innerReg
1105+ content
1106+ pure (content', content')
1107+ -- At this point, we've flushed the write buffer but we haven't created the
1108+ -- snapshot file yet. If an asynchronous exception happens beyond this
1109+ -- point, we'll take that loss, as the inner state of the table is still
1110+ -- consistent.
1111+
1112+ -- Convert to snapshot format
1113+ snapLevels <- toSnapLevels (tableLevels content)
1114+ -- Hard link runs into the named snapshot directory
1115+ snapLevels' <- snapshotRuns reg snapDir snapLevels
1116+
1117+ let snapMetaData = SnapshotMetaData label tableType (tableConfig t) snapLevels'
1118+ SnapshotMetaDataFile contentPath = Paths. snapshotMetaDataFile snapDir
1119+ SnapshotMetaDataChecksumFile checksumPath = Paths. snapshotMetaDataChecksumFile snapDir
1120+ writeFileSnapshotMetaData hfs contentPath checksumPath snapMetaData
11161121
11171122{-# SPECIALISE openSnapshot ::
11181123 Session IO h
@@ -1150,7 +1155,7 @@ openSnapshot sesh label tableType override snap resolve = do
11501155 Left e -> throwIO (ErrSnapshotDeserialiseFailure e snap)
11511156 Right x -> pure x
11521157
1153- let SnapshotMetaData label' tableType' conf snappedLevels = snapMetaData
1158+ let SnapshotMetaData label' tableType' conf snapLevels = snapMetaData
11541159
11551160 unless (tableType == tableType') $
11561161 throwIO (ErrSnapshotWrongTableType snap tableType tableType')
@@ -1168,8 +1173,11 @@ openSnapshot sesh label tableType override snap resolve = do
11681173 WBB. removeReference
11691174
11701175 let actDir = Paths. activeDir (sessionRoot seshEnv)
1171- snappedLevels' <- openRuns hfs hbio conf (sessionUniqCounter seshEnv) snapDir actDir snappedLevels
1172- tableLevels <- openLevels reg hfs hbio conf (sessionUniqCounter seshEnv) resolve actDir snappedLevels'
1176+
1177+ -- Hard link runs into the active directory,
1178+ snapLevels' <- openRuns reg hfs hbio conf (sessionUniqCounter seshEnv) snapDir actDir snapLevels
1179+ -- Convert from the snapshot format, restoring merge progress in the process
1180+ tableLevels <- fromSnapLevels reg hfs hbio conf (sessionUniqCounter seshEnv) resolve actDir snapLevels'
11731181
11741182 tableCache <- mkLevelsCache reg tableLevels
11751183 newWith reg sesh seshEnv conf' am $! TableContent {
0 commit comments