def detect_corruption(self, fname): """ single disk corruption detection :param fname: data name in RAID6 system :return: corrupted disk index; for p, self.N-2; for q, self.N-1 """ # all disks, including P, Q byte_ndarray = self._read_n(fname, self.N) data_ndarray = byte_ndarray[:-2] self._logger.info("byte_ndarray=\n{}".format(byte_ndarray)) P = byte_ndarray[-2:-1] self._logger.info("p={}".format(P)) Q = byte_ndarray[-1] self._logger.info("Q={}".format(Q)) P_prime = utils.gen_p(data_ndarray, ndim=2) self._logger.info("P_prime={}".format(P_prime)) Q_prime = utils.gen_q(data_ndarray, ndim=2) self._logger.info("Q_prime={}".format(Q_prime)) P_star = np.bitwise_xor(P, P_prime) Q_star = np.bitwise_xor(Q, Q_prime) P_nonzero = np.count_nonzero(P_star) Q_nonzero = np.count_nonzero(Q_star) if P_nonzero == 0 and Q_nonzero == 0: print("no corruption") return None elif P_nonzero == 0 and Q_nonzero != 0: print("Q corruption") return self.N - 1 elif P_nonzero != 0 and Q_nonzero == 0: print("P corruption") return self.N - 2 else: index = self._get_corrupted_data_disk(P_star, Q_star) print("data disk {} corruption".format(index)) return index
def recover_d_p(self, fname, index): """ recover data drive (index) and 'p' drive :param fname: data name :param index: data disk index :return: """ assert 0 <= index < self.N - 2 byte_ndarray = self._read_n(fname, self.N, exclude=index) DD = byte_ndarray[:-2] Q = byte_ndarray[-1:] # Dx Qx = utils.gen_q(DD, ndim=2) g_x_inv = self.gf.generator[(self.gf.circle - index) % self.gf.circle] ### _add_list = utils.gf_1darray_add(Q, Qx) Dx_list = utils.gf_a_multiply_list(g_x_inv, _add_list) ### Dx_content = ''.join(chr(i) for i in Dx_list) x_fpath = self.get_real_name(index, fname) utils.write_content(x_fpath, Dx_content) # p Dx = np.array(Dx_list, ndmin=2) assert Dx.shape[1] == byte_ndarray.shape[1] # update firstly DD[index] = Dx P = utils.gen_p(DD, ndim=1) assert P.shape[0] == byte_ndarray.shape[1] # do not need to update DD P_content = self._1darray_to_str(P) P_path = self.get_real_name(self.N - 2, fname) utils.write_content(P_path, P_content)
def recover_2d(self, fname, x, y): """ recover data drives (x and y) :param fname: data name :param x: corrupted data disk index :param y: corrupted data disk index :return: """ assert 0 <= x < self.N - 2 assert 0 <= y < self.N - 2 assert x != y byte_ndarray = self._read_n(fname, self.N, exclude=[x, y]) DD = byte_ndarray[:-2] P = byte_ndarray[-2:-1] Q = byte_ndarray[-1:] # Pxy Pxy = utils.gen_p(DD, ndim=2) # Qxy Qxy = utils.gen_q(DD, ndim=2) # Axy, Bxy A = self.gf.Axy(x, y) B = self.gf.Bxy(x, y) # Dx first = utils.gf_a_multiply_list(A, utils.gf_1darray_add(P, Pxy)) second = utils.gf_a_multiply_list(B, utils.gf_1darray_add(Q, Qxy)) Dx = utils.gf_1darray_add(np.array(first, dtype=config.BYTE_TYPE), np.array(second, dtype=config.BYTE_TYPE)) Dx_content = self._1darray_to_str(Dx) x_fpath = self.get_real_name(x, fname) utils.write_content(x_fpath, Dx_content) # Dy Dy = utils.gf_1darray_add(P ^ Pxy, Dx) Dy_content = self._1darray_to_str(Dy) y_fpath = self.get_real_name(y, fname) utils.write_content(y_fpath, Dy_content)
def write(self, content, fname): """ write content to fname(in RAID6 system) """ byte_ndarray = self._gen_ndarray_from_content(content, self.N - 2) p_ndarray = utils.gen_p(byte_ndarray, ndim=2) q_ndarray = utils.gen_q(byte_ndarray, ndim=2) write_ndarray = np.concatenate([byte_ndarray, p_ndarray, q_ndarray]) self._write_n(fname, write_ndarray, self.N)
def recover_q(self, fname): """ recover 'q' drive, recompute :param fname: data name :return: """ byte_ndarray = self._read_n(fname, self.N - 2) q_ndarray = utils.gen_q(byte_ndarray, ndim=2) assert q_ndarray.ndim == 2 new_num = q_ndarray.shape[1] q_ndarray.shape = (new_num, ) content = self._1darray_to_str(q_ndarray) fpath = self.get_real_name(self.N - 1, fname) utils.write_content(fpath, content)
def recover_q(self, fname): """ recover 'q' drive, recompute :param fname: data name :return: """ byte_ndarray = self._read_n(fname, self.N - 2) q_ndarray = utils.gen_q(byte_ndarray, ndim=2) assert q_ndarray.ndim == 2 new_num = q_ndarray.shape[1] q_ndarray.shape = (new_num,) content = self._1darray_to_str(q_ndarray) fpath = self.get_real_name(self.N - 1, fname) utils.write_content(fpath, content)
def recover_2d(self, fname, x, y): """ recover data drives (x and y) :param fname: data name :param x: corrupted data disk index :param y: corrupted data disk index :return: """ assert 0 <= x < self.N - 2 assert 0 <= y < self.N - 2 assert x != y byte_ndarray = self._read_n(fname, self.N, exclude=[x, y]) DD = byte_ndarray[:-2] P = byte_ndarray[-2:-1] Q = byte_ndarray[-1:] # Pxy Pxy = utils.gen_p(DD, ndim=2) # Qxy Qxy = utils.gen_q(DD, ndim=2) # Axy, Bxy A = self.gf.Axy(x, y) B = self.gf.Bxy(x, y) # Dx first = utils.gf_a_multiply_list(A, utils.gf_1darray_add(P, Pxy)) second = utils.gf_a_multiply_list(B, utils.gf_1darray_add(Q, Qxy)) Dx = utils.gf_1darray_add( np.array( first, dtype=config.BYTE_TYPE), np.array( second, dtype=config.BYTE_TYPE)) Dx_content = self._1darray_to_str(Dx) x_fpath = self.get_real_name(x, fname) utils.write_content(x_fpath, Dx_content) # Dy Dy = utils.gf_1darray_add(P ^ Pxy, Dx) Dy_content = self._1darray_to_str(Dy) y_fpath = self.get_real_name(y, fname) utils.write_content(y_fpath, Dy_content)