コード例 #1
0
        public void ReedsolomonRepairTest()
        {
            int nData     = 100;
            int nParity   = 25;
            int nMessages = 1000;
            int nErrors   = 20;

            Random r = new Random(1234);

            byte[][] data     = new byte[nData][];
            byte[][] original = new byte[nData][];

            for (int i = 0; i < nData; i++)
            {
                data[i]     = new byte[nMessages];
                original[i] = new byte[nMessages];
                r.NextBytes(data[i]);
                for (int j = 0; j < nMessages; j++)
                {
                    original[i][j] = data[i][j];
                }
            }

            byte[][] parity = new byte[nParity][];
            for (int i = 0; i < nParity; i++)
            {
                parity[i] = new byte[nMessages * sizeof(ushort)];
            }

            using (Parity p = new Parity(nData, nParity, nMessages / 2)) {
                for (int i = 0; i < nData; i++)
                {
                    p.Calculate(data[i], 0, nData + nParity - 1 - i);
                }
                for (int i = 0; i < nParity; i++)
                {
                    p.GetParity(parity[i], 0, nParity - 1 - i);
                }
            }

            List <int> choices        = Enumerable.Range(0, nData + nParity).ToList();
            List <int> errorExponents = new List <int>();

            for (int i = 0; i < nErrors; i++)
            {
                int l = r.Next(choices.Count);
                errorExponents.Add(choices[l]);
                choices.RemoveAt(l);
            }

            foreach (var errorExponent in errorExponents)
            {
                byte[] d = errorExponent < nParity ? parity[nParity - 1 - errorExponent] : data[nData + nParity - 1 - errorExponent];
                r.NextBytes(d);
            }

            using (Syndrome s = new Syndrome(nData, nParity, nMessages / 2)) {
                for (int i = 0; i < nData; i++)
                {
                    s.AddCodewordSlice(data[i], 0, nData + nParity - 1 - i);
                }
                for (int i = 0; i < nParity; i++)
                {
                    s.AddCodewordSlice(parity[i], 0, nParity - 1 - i);
                }

                using (Repair repair = new Repair(s, nData + nParity, errorExponents)) {
                    int index = 0;
                    foreach (var errorExponent in errorExponents)
                    {
                        byte[] d = errorExponent < nParity ? parity[nParity - 1 - errorExponent] : data[nData + nParity - 1 - errorExponent];
                        repair.Correction(index, d, 0);
                        index++;
                    }
                }
            }

            for (int i = 0; i < nData; i++)
            {
                Assert.IsTrue(data[i].SequenceEqual(original[i]));
            }
        }
コード例 #2
0
ファイル: Track.cs プロジェクト: FrozenWasteland/SRFS2
        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);
                }
            }
        }