1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <string>
#include <deque>
#include <algorithm>
#include <tuple>
using namespace std;
int n, s, l;
vector<string> RAIDArray;
int diskBlockCount;
char buf[100];
void input(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n>>s>>l;
RAIDArray.resize(n);
for(int i=0;i<l;i++){
int diskID, data;
int bCnt = 0;
string s;
cin>>diskID>>s;
RAIDArray[diskID]=s;
diskBlockCount = s.size() / 8;
}
}
int RAID(int diskID, int localBlockID){
int data;
sscanf((char *)&RAIDArray[diskID].c_str()[localBlockID*8],"%8X",&data);
return data;
}
inline bool isDiskExists(int diskID){
return !RAIDArray[diskID].empty();
}
inline int getGlobalStripeID(int blockID){
return blockID / s;
}
inline int getLocalStripeID(int globalStripeID){
return globalStripeID / (n-1);
}
inline int getlocalStripeECCDiskID(int localStripeID){
return n - 1 - localStripeID % n;
}
inline std::tuple<int, int> getLocalDiskAndBlockID(int blockID){
// Return Disk ID, Local Block ID
int globalStripeID = getGlobalStripeID(blockID);
int localStripeID = getLocalStripeID(globalStripeID);
int localStripeECCDiskID = getlocalStripeECCDiskID(localStripeID);
int localStripeDiskID = (localStripeECCDiskID + 1 + globalStripeID % (n-1)) % n;
int localBlockID = localStripeID * s + blockID % s;
return std::tuple<int, int>(localStripeDiskID, localBlockID);
}
inline std::tuple<bool, int> recoverDataDirect(int blockID){
int diskID, localBlockID;
std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
if(!isDiskExists(diskID))
return std::tuple<bool, int>(false, -1);
else
return std::tuple<bool, int>(true, RAID(diskID, localBlockID));
}
inline std::tuple<bool, int> recoverDataECC(int blockID){
if(l < n-1)
return std::tuple<bool, int>(false, -1);
int diskID, localBlockID;
int data = 0;
std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
for(int curDisk = 0;curDisk<n;curDisk++){
if(curDisk == diskID)continue;
data ^= RAID(curDisk,localBlockID);
}
return std::tuple<bool, int>(true, data);
}
inline std::tuple<bool, int> recoverDataMain(int blockID){
int diskID, localBlockID;
std::tie(diskID, localBlockID) = getLocalDiskAndBlockID(blockID);
if(localBlockID >= diskBlockCount)
return std::tuple<bool, int> (false, -1);
bool flag;
int result;
std::tie(flag, result) = recoverDataDirect(blockID);
if(flag)
return std::tuple<bool, int> (flag, result);
std::tie(flag, result) = recoverDataECC(blockID);
if(flag)
return std::tuple<bool, int> (flag, result);
return std::tuple<bool, int> (false, -1);
}
void solve(){
int m, blockID;
cin>>m;
while(m--){
cin>>blockID;
bool flag;
int result;
tie(flag, result) = recoverDataMain(blockID);
if(!flag)
cout<<"-\n";
else
cout<<setw(8)<<setfill('0')<<hex<<uppercase<<result<<"\n";
}
}
int main(){
input();
solve();
} |