public void UpdateParity(bool force = false) { if (!force && !DataModified && ParityWritten) { return; } int dataClustersPerTrack = Configuration.Geometry.DataClustersPerTrack; int parityClustersPerTrack = Configuration.Geometry.ParityClustersPerTrack; int bytesPerCluster = Configuration.Geometry.BytesPerCluster; using (var p = new Parity(dataClustersPerTrack, parityClustersPerTrack, bytesPerCluster / 2)) { int codewordExponent = dataClustersPerTrack + parityClustersPerTrack - 1; byte[] emptyCluster = null; foreach (var absoluteClusterNumber in DataClusters) { ClusterState state = _fileSystem.GetClusterState(absoluteClusterNumber); if (!state.IsSystem()) { if ((state & ClusterState.Unwritten) != 0) { if (emptyCluster == null) { EmptyCluster c = new EmptyCluster(absoluteClusterNumber); Console.WriteLine($"Saving empty cluster {absoluteClusterNumber}"); _fileSystem.ClusterIO.Save(c); emptyCluster = new byte[bytesPerCluster]; c.Save(emptyCluster, 0); } p.Calculate(emptyCluster, 0, codewordExponent); state &= ~ClusterState.Unwritten; _fileSystem.SetClusterState(absoluteClusterNumber, state); } else { Cluster c = new Cluster(absoluteClusterNumber, bytesPerCluster); Console.WriteLine($"Loading cluster {absoluteClusterNumber}"); _fileSystem.ClusterIO.Load(c); byte[] bytes = new byte[bytesPerCluster]; c.Save(bytes, 0); p.Calculate(bytes, 0, codewordExponent); } } codewordExponent--; } for (int i = 0; i < parityClustersPerTrack; i++) { ParityCluster c = new ParityCluster(_fileSystem.BlockSize, _trackNumber, i); byte[] bytes = new byte[bytesPerCluster]; p.GetParity(bytes, 0, parityClustersPerTrack - 1 - i); c.Data.Set(0, bytes); Console.WriteLine($"Saving Parity Cluster {c.ClusterAddress}"); _fileSystem.ClusterIO.Save(c); _fileSystem.SetClusterState(c.ClusterAddress, ClusterState.Parity); } } // Update states after the parity is modified in case there is an error foreach (var i in DataClusters) { ClusterState state = _fileSystem.GetClusterState(i) & (~ClusterState.Modified); _fileSystem.SetClusterState(i, state); } }
private bool IsClusterDirty(ClusterState s) => (!s.IsSystem()) && (s.IsModified() | s.IsUnwritten());
private void updateParityAsyncInternal(bool force, UpdateParityStatus status, CancellationToken token) { if (!force && !DataModified && ParityWritten) { return; } int dataClustersPerTrack = Configuration.Geometry.DataClustersPerTrack; int parityClustersPerTrack = Configuration.Geometry.ParityClustersPerTrack; int bytesPerCluster = Configuration.Geometry.BytesPerCluster; using (var p = new Parity(dataClustersPerTrack, parityClustersPerTrack, bytesPerCluster / 2)) { int codewordExponent = dataClustersPerTrack + parityClustersPerTrack - 1; byte[] emptyCluster = null; int clustersComplete = -1; foreach (var absoluteClusterNumber in DataClusters) { ClusterState state = _fileSystem.GetClusterState(absoluteClusterNumber); if (!state.IsSystem()) { if ((state & ClusterState.Unwritten) != 0) { if (emptyCluster == null) { EmptyCluster c = new EmptyCluster(absoluteClusterNumber); _fileSystem.ClusterIO.Save(c); emptyCluster = new byte[bytesPerCluster]; c.Save(emptyCluster, 0); } p.Calculate(emptyCluster, 0, codewordExponent); state &= ~ClusterState.Unwritten; _fileSystem.SetClusterState(absoluteClusterNumber, state); } else { Cluster c = new Cluster(absoluteClusterNumber, bytesPerCluster); _fileSystem.ClusterIO.Load(c); byte[] bytes = new byte[bytesPerCluster]; c.Save(bytes, 0); p.Calculate(bytes, 0, codewordExponent); } } clustersComplete++; status.Cluster = clustersComplete; codewordExponent--; if (token.IsCancellationRequested) { return; } } for (int i = 0; i < parityClustersPerTrack; i++) { ParityCluster c = new ParityCluster(_fileSystem.BlockSize, _trackNumber, i); byte[] bytes = new byte[bytesPerCluster]; p.GetParity(bytes, 0, parityClustersPerTrack - 1 - i); c.Data.Set(0, bytes); _fileSystem.ClusterIO.Save(c); _fileSystem.SetClusterState(c.ClusterAddress, ClusterState.Parity); clustersComplete++; status.Cluster = clustersComplete; if (token.IsCancellationRequested) { return; } } } // Update states after the parity is modified in case there is an error foreach (var i in DataClusters) { ClusterState state = _fileSystem.GetClusterState(i) & (~ClusterState.Modified); _fileSystem.SetClusterState(i, state); } _fileSystem.Flush(); }