private void Run() { var cluster = 0; foreach (var clusterPoint in _dataSet) { if (clusterPoint.Visited) { continue; } clusterPoint.Visited = true; var neighbours = RegionQuery(clusterPoint.Vector); if (neighbours.Count < _minPoints) { clusterPoint.Noise = true; } else { cluster++; ExpandCluster(clusterPoint, neighbours, cluster); } } foreach (var clust in _dataSet.Where(x => !x.Noise).GroupBy(x => x.Cluster)) { var vectors = clust.Select(x => x.Vector); DataClusters.Add(clust.Key, vectors); } }
public bool Repair() { // We need to enforce that hashes and signatures are checked (what happens if signatures aren't? What is not protected? What happens? if (DataModified || !ParityWritten) { return(false); } int dataClustersPerTrack = Configuration.Geometry.DataClustersPerTrack; int parityClustersPerTrack = Configuration.Geometry.ParityClustersPerTrack; int bytesPerCluster = Configuration.Geometry.BytesPerCluster; List <int> errorExponents = new List <int>(); using (var p = new Syndrome(dataClustersPerTrack, parityClustersPerTrack, bytesPerCluster / 2)) { int codewordExponent = dataClustersPerTrack + parityClustersPerTrack - 1; foreach (var absoluteClusterNumber in DataClusters) { if (!_fileSystem.GetClusterState(absoluteClusterNumber).IsSystem()) { Cluster c = new Cluster(absoluteClusterNumber, bytesPerCluster); Console.WriteLine($"Loading cluster {absoluteClusterNumber}"); try { _fileSystem.ClusterIO.Load(c); byte[] bytes = new byte[bytesPerCluster]; c.Save(bytes, 0); p.AddCodewordSlice(bytes, 0, codewordExponent); } catch (System.IO.IOException) { // We need to catch something specific to a hash failure or something. Or force no auto check, then check manually. Console.WriteLine($"Error in data cluster {absoluteClusterNumber}"); errorExponents.Add(codewordExponent); } } codewordExponent--; } int parityNumber = 0; foreach (var absoluteClusterNumber in ParityClusters) { ParityCluster c = new ParityCluster(_fileSystem.BlockSize, _trackNumber, parityNumber); Console.WriteLine($"Loading parity cluster {absoluteClusterNumber}"); try { _fileSystem.ClusterIO.Load(c); byte[] bytes = c.Data.ToByteArray(0, bytesPerCluster); p.AddCodewordSlice(bytes, 0, codewordExponent); } catch (System.IO.IOException) { Console.WriteLine($"Error in parity cluster {absoluteClusterNumber}"); errorExponents.Add(codewordExponent); } codewordExponent--; parityNumber++; } if (errorExponents.Count == 0) { byte[] values = new byte[bytesPerCluster]; for (int i = 0; i < parityClustersPerTrack; i++) { p.GetSyndromeSlice(values, 0, i); for (int j = 0; j < bytesPerCluster; j++) { if (values[j] != 0) { return(false); } } } return(true); } else { // Throw an exception or specify the error somehow if (errorExponents.Count > parityClustersPerTrack) { return(false); } using (var r = new Repair(p, dataClustersPerTrack + parityClustersPerTrack, errorExponents)) { byte[] bytes = new byte[bytesPerCluster]; int[] dataClusters = DataClusters.ToArray(); int index = 0; foreach (var e in errorExponents) { r.Correction(index++, bytes, 0); if (e < parityClustersPerTrack) { // it is a parity cluster ParityCluster c = new ParityCluster(_fileSystem.BlockSize, _trackNumber, parityClustersPerTrack - 1 - e); c.Data.Set(0, bytes); Console.WriteLine($"Repairing parity {c.ClusterAddress} at {c.AbsoluteAddress}"); _fileSystem.ClusterIO.Save(c); } else { // Need to do this without creating a cluster, since that will change the signature int i = dataClustersPerTrack + parityClustersPerTrack - 1 - e; Cluster c = new Cluster(dataClusters[i], bytesPerCluster); c.Load(bytes, 0); Console.WriteLine($"Repairing data {c.ClusterAddress} at {c.AbsoluteAddress}"); _fileSystem.ClusterIO.Save(c); } } } return(true); } } }