509 - RAID!

来源:互联网 发布:怎么跟网络管理员联系 编辑:程序博客网 时间:2024/06/07 00:47

RAID (Redundant Array of Inexpensive Disks)is a technique which uses multiple disks to store data. By storing the data onmore than one disk, RAID is more fault tolerant than storing data on a singledisk. If there is a problem with one of the disks, the system can still recoverthe original data provided that the remaining disks do not have correspondingproblems.


One approach to RAID breaks data into blocks and stores these blocks on all butone of the disks. The remaining disk is used to store the parity informationfor the data blocks. This scheme uses vertical parity in whichbits in a given position in data blocks are exclusive ORed to form thecorresponding parity bit. The parity block moves between the disks, starting atthe first disk, and moving to the next one in order. For instance, if therewere five disks and 28 data blocks were stored on them, they would be arrangedas follows:

 

Disk 1

Disk 2

Disk 3

Disk 4

Disk 5

Parity for 1-4

Data block 1

Data block 2

Data block 3

Data block 4

Data block 5

Parity for 5-8

Data block 6

Data block 7

Data block 8

Data block 9

Data block 10

Parity for 9-12

Data block 11

Data block 12

Data block 13

Data block 14

Data block 15

Parity for 13-16

Data block 16

Data block 17

Data block 18

Data block 19

Data block 20

Parity for 17-20

Parity for 21-24

Data block 21

Data block 22

Data block 23

Data block 24

Data block 25

Parity for 25-28

Data block 26

Data block 27

Data block 28


With this arrangement of disks, a block size of two bits and even parity,the hexadecimal sample data 6C7A79EDFC (01101100 01111010 01111001 1110110111111100 in binary) would be stored as:

 

Disk 1

Disk 2

Disk 3

Disk 4

Disk 5

00

01

10

11

00

01

10

11

10

10

01

11

01

10

01

11

10

11

11

01

11

11

11

00

11


If a block becomes unavailable, its information can still be retrieved usingthe information on the other disks. For example, if the first bit of the firstblock of disk 3 becomes unavailable, it can be reconstructed using thecorresponding parity and data bits from the other four disks. We know that oursample system uses even parity:

 


So the missing bit must be 1.


An arrangement of disks is invalid if a parity error is detected, or if anydata block cannot be reconstructed because two or more disks are unavailablefor that block.


Write a program to report errors and recover information from RAID disks.

Input 

The input consists ofseveral disk sets.


Each disk set has 3 parts. The first part of the disk set contains threeintegers on one line: the first integer d, , is the number ofdisks, the second integer s, , is the size ofeach block in bits, and the third integer b, , is the totalnumber of data and parity blocks on each disk. The second part of the disk setis a single letter on a line, either ``E'' signifying even parity or ``O''signifying odd parity. The third part of the disk set contains d lines,one for each disk, each holding  charactersrepresenting the bits on the disk, with the most significant bits first. Eachbit will be specified as ``0'' or ``1'' if it holds valid data, or ``x'' ifthat bit is unavailable. The end of input will be a disk set with d =0. There will be no other data for this set which should not be processed.

Output 

For each disk set in theinput, display the number of the set and whether the set is valid or invalid.If the set is valid, display the recovered data bits in hexadecimal. Ifnecessary, add extra ``0'' bits at the end of the recovered data so the numberof bits is always a multiple of 4. All output shall be appropriately labeled.

Sample Input 

5 2 5

E

0001011111

0110111011

1011011111

1110101100

0010010111

3 2 5

E

0001111111

0111111011

xx11011111

3 5 1

O

11111

11xxx

x1111

0      

Sample Output 

Disk set 1 is valid, contents are:6C7A79EDFC

Disk set 2 is invalid.

Disk set 3 is valid, contents are: FFC

 

 

错误但是没找出错误的代码:

#include<iostream>

#include<cstring>

#include<iomanip>

using namespacestd;

struct RAID

{

    int n=0;

    int data[6*64*100+100]= {0};

    bool operate(int d,int s,int b)

    {

        int parity=0;

        char ch;

        char content[7][6*64*100+100];

        cin>>ch;

        if(ch=='O')

        {

            parity=1;

        }

        for(int i=0; i<d; i++)

        {

            for(int j=0; j<s*b; j++)

            {

                cin>>content[i][j];

            }

        }

        int xnum[6410]= {0};

        int exor[6410]= {0};

        for(int i=0; i<d; i++)

        {

            for(int j=0; j<s*b; j++)

            {

                if(content[i][j]=='x')

                {

                    xnum[j]++;

                }

                else

                {

                   exor[j]=exor[j]^(content[i][j]-'0');

                }

            }

        }

        for(int j=0; j<s*b; j++)

        {

            if(xnum[j]>1)

            {

                return false;

            }

           if(xnum[j]==0&&exor[j]!=parity)

            {

                return false;

            }

            for(int i=0; i<d; i++)

            {

                if(content[i][j]=='x')

                {

                   content[i][j]=(exor[j]^parity+'0');

                }

            }

        }

        for(int j=0; j<s*b; j=j+s)

        {

            for(int i=0; i<d; i++)

            {

                if(i==(j/s)%d)

                {

                    continue;

                }

                for(int k=0; k<s; k++)

                {

                   data[n++]=(content[i][j+k]-'0');

                }

            }

        }

        while(n%4!=0)

        {

            data[n++]=0;

        }

        return true;

    }

    void print()

    {

        int result=0;

        for(int i=0; i<n; i=i+4)

        {

           result=data[i]*8+data[i+1]*4+data[i+2]*2+data[i+3]*1;

           cout<<setiosflags(ios::uppercase)<<hex<<result;

        }

        cout<<endl;

    }

};

int main()

{

    int time=1;

    int d,s,b;

    while(cin>>d&&d!=0)

    {

        cin>>s>>b;

        RAID A;

        memset(&A,0,sizeof(A));

        if(A.operate(d,s,b))

        {

            cout<<"Disk set"<<time<<" is valid, contents are: ";

            A.print();

            time++;

        }

        else

        {

            cout<<"Disk set"<<time<<" is invalid.\n";

            time++;

        }

    }

    return 0;

}

 

 

 

参考代码及思路:

/*

构造了一个RAID类,用一个bool类型的大数组data存储0、1正文信息

整数n代表存了多少位。然后关键是Set成员函数的实现。

Set函数尝试将数据读入与恢复,并存储在data中,

如果失败则返回0,否则返回1。

Set函数的算法和步骤是本题的核心:

它先统计每列的'x'个数,已有的01也先做异或运算。

然后做列检验,如果该列没有'x',则异或结果错误的return 0;

如果该列有一个'x',直接对其进行恢复;

如果有多个'x'的,肯定有正文信息损坏且无法恢复,故也return 0。

step 2若能顺利执行,进入该步,则此时str中一定不存在'x'。

用技巧来依次读取正文即可。*/

#include<cstdio>

#include<iostream>

using namespacestd;

 

struct RAID

{

    int n;

    bool data[64*100*6+10];

 

    int Set(int d, int s, int b)

    {

        bool parity = 0;

        char str[7][6410], str1[10];

        // 读入数据

        scanf("%s", str1);

        if (str1[0]=='O')

        {

            parity = 1;

        }

 

        for (int i = 0; i < d; i++)

        {

            scanf("%s", str[i]);

        }

 

        // 统计每列有多少个x, 并统计已有01的异或值

        int cnt[6410] = {}, i, j;

        bool check[6410] = {};

        for (i = 0; i < d; i++)

        {

            for (j = 0; j < s*b; j++)

            {

                if (str[i][j]=='x')

                {

                    cnt[j]++;

                }

                else

                {

                    check[j] ^=(str[i][j]-'0');

                }

            }

        }

 

        for (j = 0; j < s*b; j++)   // 每列校验

        {

            if (cnt[j] > 1)

            {

                return 0;

            }

 

            if (cnt[j] == 0 && check[j]!= parity)

            {

                return 0;

            }

 

            // 否则只有一个x,直接恢复

            for (i = 0; i < d; i++)

            {

                if (str[i][j]=='x')

                {

                    str[i][j] =(parity^check[j]) + '0';

                    break;

                }

            }

 

        }

        // 生成数据data,遇到'x'时return 0

        for (n = j = 0; j < s*b; j += s)

        {

            for (i = 0; i < d; i++)

            {

                if (i == (j/s)%d)

                {

                    continue;

                }// 注意此处技巧,巧妙的跳过校验码

 

                for (int k = 0; k < s; k++)

                {

                    data[n++] =str[i][j+k]-'0';

                }

            }

            while (n%4 != 0)

            {

                data[n++] = 0;

            }

 

            return 1;

        }

 

        void out()

        {

            for (int i = 0; i < n; i += 4)

            {

                printf("%X",data[i]*8 + data[i+1]*4 + data[i+2]*2 + data[i+3]);

            }

            putchar('\n');

        }

    }

};

 

int main()

{

    int d, s, b, kase = 0;

    RAID A;

    while (cin >> d >> s >> b)

    {

        if (A.Set(d, s, b))

        {

            printf("Disk set %d is valid,contents are: ", ++kase);

            A.out();

        }

        else

        {

            printf("Disk set %d isinvalid.\n", ++kase);

        }

    }

    return 0;

}

 

0 0