예제 #1
0
        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);
            }
        }
예제 #2
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]));
            }
        }
예제 #3
0
        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();
        }