Search in sources :

Example 1 with CorruptHFileException

use of org.apache.hadoop.hbase.io.hfile.CorruptHFileException in project hbase by apache.

the class HMobStore method readCell.

/**
 * Reads the cell from a mob file.
 * The mob file might be located in different directories.
 * 1. The working directory.
 * 2. The archive directory.
 * Reads the cell from the files located in both of the above directories.
 * @param locations The possible locations where the mob files are saved.
 * @param fileName The file to be read.
 * @param search The cell to be searched.
 * @param cacheMobBlocks Whether the scanner should cache blocks.
 * @param readPt the read point.
 * @param readEmptyValueOnMobCellMiss Whether return null value when the mob file is
 *        missing or corrupt.
 * @return The found cell. Null if there's no such a cell.
 * @throws IOException
 */
private MobCell readCell(List<Path> locations, String fileName, Cell search, boolean cacheMobBlocks, long readPt, boolean readEmptyValueOnMobCellMiss) throws IOException {
    FileSystem fs = getFileSystem();
    Throwable throwable = null;
    for (Path location : locations) {
        MobFile file = null;
        Path path = new Path(location, fileName);
        try {
            file = mobFileCache.openFile(fs, path, getCacheConfig());
            return readPt != -1 ? file.readCell(search, cacheMobBlocks, readPt) : file.readCell(search, cacheMobBlocks);
        } catch (IOException e) {
            mobFileCache.evictFile(fileName);
            throwable = e;
            if ((e instanceof FileNotFoundException) || (e.getCause() instanceof FileNotFoundException)) {
                LOG.debug("Fail to read the cell, the mob file " + path + " doesn't exist", e);
            } else if (e instanceof CorruptHFileException) {
                LOG.error("The mob file " + path + " is corrupt", e);
                break;
            } else {
                throw e;
            }
        } catch (NullPointerException e) {
            // HDFS 1.x - DFSInputStream.getBlockAt()
            mobFileCache.evictFile(fileName);
            LOG.debug("Fail to read the cell", e);
            throwable = e;
        } catch (AssertionError e) {
            // assert in HDFS 1.x - DFSInputStream.getBlockAt()
            mobFileCache.evictFile(fileName);
            LOG.debug("Fail to read the cell", e);
            throwable = e;
        } finally {
            if (file != null) {
                mobFileCache.closeFile(file);
            }
        }
    }
    LOG.error("The mob file " + fileName + " could not be found in the locations " + locations + " or it is corrupt");
    if (readEmptyValueOnMobCellMiss) {
        return null;
    } else if ((throwable instanceof FileNotFoundException) || (throwable.getCause() instanceof FileNotFoundException)) {
        // doesn't help fix the lost MOB files.
        throw new DoNotRetryIOException(throwable);
    } else if (throwable instanceof IOException) {
        throw (IOException) throwable;
    } else {
        throw new IOException(throwable);
    }
}
Also used : Path(org.apache.hadoop.fs.Path) DoNotRetryIOException(org.apache.hadoop.hbase.DoNotRetryIOException) FileSystem(org.apache.hadoop.fs.FileSystem) FileNotFoundException(java.io.FileNotFoundException) CorruptHFileException(org.apache.hadoop.hbase.io.hfile.CorruptHFileException) DoNotRetryIOException(org.apache.hadoop.hbase.DoNotRetryIOException) IOException(java.io.IOException) MobFile(org.apache.hadoop.hbase.mob.MobFile)

Example 2 with CorruptHFileException

use of org.apache.hadoop.hbase.io.hfile.CorruptHFileException in project hbase by apache.

the class FaultyMobStoreCompactor method performCompaction.

@Override
protected boolean performCompaction(FileDetails fd, InternalScanner scanner, long smallestReadPoint, boolean cleanSeqId, ThroughputController throughputController, boolean major, int numofFilesToCompact) throws IOException {
    totalCompactions.incrementAndGet();
    if (major) {
        totalMajorCompactions.incrementAndGet();
    }
    long bytesWrittenProgressForLog = 0;
    long bytesWrittenProgressForShippedCall = 0;
    // Clear old mob references
    mobRefSet.get().clear();
    boolean isUserRequest = userRequest.get();
    boolean compactMOBs = major && isUserRequest;
    boolean discardMobMiss = conf.getBoolean(MobConstants.MOB_UNSAFE_DISCARD_MISS_KEY, MobConstants.DEFAULT_MOB_DISCARD_MISS);
    boolean mustFail = false;
    if (compactMOBs) {
        mobCounter.incrementAndGet();
        double dv = rnd.nextDouble();
        if (dv < failureProb) {
            mustFail = true;
            totalFailures.incrementAndGet();
        }
    }
    FileSystem fs = store.getFileSystem();
    // Since scanner.next() can return 'false' but still be delivering data,
    // we have to use a do/while loop.
    List<Cell> cells = new ArrayList<>();
    // Limit to "hbase.hstore.compaction.kv.max" (default 10) to avoid OOME
    long currentTime = EnvironmentEdgeManager.currentTime();
    long lastMillis = 0;
    if (LOG.isDebugEnabled()) {
        lastMillis = currentTime;
    }
    CloseChecker closeChecker = new CloseChecker(conf, currentTime);
    String compactionName = ThroughputControlUtil.getNameForThrottling(store, "compaction");
    long now = 0;
    boolean hasMore;
    Path path = MobUtils.getMobFamilyPath(conf, store.getTableName(), store.getColumnFamilyName());
    byte[] fileName = null;
    StoreFileWriter mobFileWriter = null;
    long mobCells = 0;
    long cellsCountCompactedToMob = 0, cellsCountCompactedFromMob = 0;
    long cellsSizeCompactedToMob = 0, cellsSizeCompactedFromMob = 0;
    boolean finished = false;
    ScannerContext scannerContext = ScannerContext.newBuilder().setBatchLimit(compactionKVMax).build();
    throughputController.start(compactionName);
    KeyValueScanner kvs = (scanner instanceof KeyValueScanner) ? (KeyValueScanner) scanner : null;
    long shippedCallSizeLimit = (long) numofFilesToCompact * this.store.getColumnFamilyDescriptor().getBlocksize();
    Cell mobCell = null;
    long counter = 0;
    long countFailAt = -1;
    if (mustFail) {
        // randomly fail fast
        countFailAt = rnd.nextInt(100);
    }
    try {
        try {
            mobFileWriter = mobStore.createWriterInTmp(new Date(fd.latestPutTs), fd.maxKeyCount, major ? majorCompactionCompression : minorCompactionCompression, store.getRegionInfo().getStartKey(), true);
            fileName = Bytes.toBytes(mobFileWriter.getPath().getName());
        } catch (IOException e) {
            // Bailing out
            LOG.error("Failed to create mob writer, ", e);
            throw e;
        }
        if (compactMOBs) {
            // Add the only reference we get for compact MOB case
            // because new store file will have only one MOB reference
            // in this case - of newly compacted MOB file
            mobRefSet.get().put(store.getTableName(), mobFileWriter.getPath().getName());
        }
        do {
            hasMore = scanner.next(cells, scannerContext);
            currentTime = EnvironmentEdgeManager.currentTime();
            if (LOG.isDebugEnabled()) {
                now = currentTime;
            }
            if (closeChecker.isTimeLimit(store, currentTime)) {
                progress.cancel();
                return false;
            }
            for (Cell c : cells) {
                counter++;
                if (compactMOBs) {
                    if (MobUtils.isMobReferenceCell(c)) {
                        if (counter == countFailAt) {
                            LOG.warn("INJECTED FAULT mobCounter={}", mobCounter.get());
                            throw new CorruptHFileException("injected fault");
                        }
                        String fName = MobUtils.getMobFileName(c);
                        // Added to support migration
                        try {
                            mobCell = mobStore.resolve(c, true, false).getCell();
                        } catch (DoNotRetryIOException e) {
                            if (discardMobMiss && e.getCause() != null && e.getCause() instanceof FileNotFoundException) {
                                LOG.error("Missing MOB cell: file={} not found cell={}", fName, c);
                                continue;
                            } else {
                                throw e;
                            }
                        }
                        if (discardMobMiss && mobCell.getValueLength() == 0) {
                            LOG.error("Missing MOB cell value: file={} cell={}", fName, mobCell);
                            continue;
                        }
                        if (mobCell.getValueLength() > mobSizeThreshold) {
                            // put the mob data back to the store file
                            PrivateCellUtil.setSequenceId(mobCell, c.getSequenceId());
                            mobFileWriter.append(mobCell);
                            writer.append(MobUtils.createMobRefCell(mobCell, fileName, this.mobStore.getRefCellTags()));
                            mobCells++;
                        } else {
                            // If MOB value is less than threshold, append it directly to a store file
                            PrivateCellUtil.setSequenceId(mobCell, c.getSequenceId());
                            writer.append(mobCell);
                            cellsCountCompactedFromMob++;
                            cellsSizeCompactedFromMob += mobCell.getValueLength();
                        }
                    } else {
                        // Not a MOB reference cell
                        int size = c.getValueLength();
                        if (size > mobSizeThreshold) {
                            mobFileWriter.append(c);
                            writer.append(MobUtils.createMobRefCell(c, fileName, this.mobStore.getRefCellTags()));
                            mobCells++;
                            cellsCountCompactedToMob++;
                            cellsSizeCompactedToMob += c.getValueLength();
                        } else {
                            writer.append(c);
                        }
                    }
                } else if (c.getTypeByte() != KeyValue.Type.Put.getCode()) {
                    // Not a major compaction or major with MOB disabled
                    // If the kv type is not put, directly write the cell
                    // to the store file.
                    writer.append(c);
                } else if (MobUtils.isMobReferenceCell(c)) {
                    // Not a major MOB compaction, Put MOB reference
                    if (MobUtils.hasValidMobRefCellValue(c)) {
                        int size = MobUtils.getMobValueLength(c);
                        if (size > mobSizeThreshold) {
                            // If the value size is larger than the threshold, it's regarded as a mob. Since
                            // its value is already in the mob file, directly write this cell to the store file
                            Optional<TableName> refTable = MobUtils.getTableName(c);
                            if (refTable.isPresent()) {
                                mobRefSet.get().put(refTable.get(), MobUtils.getMobFileName(c));
                                writer.append(c);
                            } else {
                                throw new IOException(String.format("MOB cell did not contain a tablename " + "tag. should not be possible. see ref guide on mob troubleshooting. " + "store=%s cell=%s", getStoreInfo(), c));
                            }
                        } else {
                            // If the value is not larger than the threshold, it's not regarded a mob. Retrieve
                            // the mob cell from the mob file, and write it back to the store file.
                            mobCell = mobStore.resolve(c, true, false).getCell();
                            if (mobCell.getValueLength() != 0) {
                                // put the mob data back to the store file
                                PrivateCellUtil.setSequenceId(mobCell, c.getSequenceId());
                                writer.append(mobCell);
                                cellsCountCompactedFromMob++;
                                cellsSizeCompactedFromMob += mobCell.getValueLength();
                            } else {
                                // If the value of a file is empty, there might be issues when retrieving,
                                // directly write the cell to the store file, and leave it to be handled by the
                                // next compaction.
                                LOG.error("Empty value for: " + c);
                                Optional<TableName> refTable = MobUtils.getTableName(c);
                                if (refTable.isPresent()) {
                                    mobRefSet.get().put(refTable.get(), MobUtils.getMobFileName(c));
                                    writer.append(c);
                                } else {
                                    throw new IOException(String.format("MOB cell did not contain a tablename " + "tag. should not be possible. see ref guide on mob troubleshooting. " + "store=%s cell=%s", getStoreInfo(), c));
                                }
                            }
                        }
                    } else {
                        LOG.error("Corrupted MOB reference: {}", c);
                        writer.append(c);
                    }
                } else if (c.getValueLength() <= mobSizeThreshold) {
                    // If the value size of a cell is not larger than the threshold, directly write it to
                    // the store file.
                    writer.append(c);
                } else {
                    // If the value size of a cell is larger than the threshold, it's regarded as a mob,
                    // write this cell to a mob file, and write the path to the store file.
                    mobCells++;
                    // append the original keyValue in the mob file.
                    mobFileWriter.append(c);
                    Cell reference = MobUtils.createMobRefCell(c, fileName, this.mobStore.getRefCellTags());
                    // write the cell whose value is the path of a mob file to the store file.
                    writer.append(reference);
                    cellsCountCompactedToMob++;
                    cellsSizeCompactedToMob += c.getValueLength();
                    // Add ref we get for compact MOB case
                    mobRefSet.get().put(store.getTableName(), mobFileWriter.getPath().getName());
                }
                int len = c.getSerializedSize();
                ++progress.currentCompactedKVs;
                progress.totalCompactedSize += len;
                bytesWrittenProgressForShippedCall += len;
                if (LOG.isDebugEnabled()) {
                    bytesWrittenProgressForLog += len;
                }
                throughputController.control(compactionName, len);
                if (closeChecker.isSizeLimit(store, len)) {
                    progress.cancel();
                    return false;
                }
                if (kvs != null && bytesWrittenProgressForShippedCall > shippedCallSizeLimit) {
                    ((ShipperListener) writer).beforeShipped();
                    kvs.shipped();
                    bytesWrittenProgressForShippedCall = 0;
                }
            }
            // logging at DEBUG level
            if (LOG.isDebugEnabled()) {
                if ((now - lastMillis) >= COMPACTION_PROGRESS_LOG_INTERVAL) {
                    String rate = String.format("%.2f", (bytesWrittenProgressForLog / 1024.0) / ((now - lastMillis) / 1000.0));
                    LOG.debug("Compaction progress: {} {}, rate={} KB/sec, throughputController is {}", compactionName, progress, rate, throughputController);
                    lastMillis = now;
                    bytesWrittenProgressForLog = 0;
                }
            }
            cells.clear();
        } while (hasMore);
        finished = true;
    } catch (InterruptedException e) {
        progress.cancel();
        throw new InterruptedIOException("Interrupted while control throughput of compacting " + compactionName);
    } catch (FileNotFoundException e) {
        LOG.error("MOB Stress Test FAILED, region: " + store.getRegionInfo().getEncodedName(), e);
        System.exit(-1);
    } catch (IOException t) {
        LOG.error("Mob compaction failed for region: " + store.getRegionInfo().getEncodedName());
        throw t;
    } finally {
        // Clone last cell in the final because writer will append last cell when committing. If
        // don't clone here and once the scanner get closed, then the memory of last cell will be
        // released. (HBASE-22582)
        ((ShipperListener) writer).beforeShipped();
        throughputController.finish(compactionName);
        if (!finished && mobFileWriter != null) {
            // Remove all MOB references because compaction failed
            mobRefSet.get().clear();
            // Abort writer
            abortWriter(mobFileWriter);
        }
    }
    if (mobFileWriter != null) {
        if (mobCells > 0) {
            // If the mob file is not empty, commit it.
            mobFileWriter.appendMetadata(fd.maxSeqId, major, mobCells);
            mobFileWriter.close();
            mobStore.commitFile(mobFileWriter.getPath(), path);
        } else {
            // If the mob file is empty, delete it instead of committing.
            abortWriter(mobFileWriter);
        }
    }
    mobStore.updateCellsCountCompactedFromMob(cellsCountCompactedFromMob);
    mobStore.updateCellsCountCompactedToMob(cellsCountCompactedToMob);
    mobStore.updateCellsSizeCompactedFromMob(cellsSizeCompactedFromMob);
    mobStore.updateCellsSizeCompactedToMob(cellsSizeCompactedToMob);
    progress.complete();
    return true;
}
Also used : StoreFileWriter(org.apache.hadoop.hbase.regionserver.StoreFileWriter) InterruptedIOException(java.io.InterruptedIOException) DoNotRetryIOException(org.apache.hadoop.hbase.DoNotRetryIOException) ArrayList(java.util.ArrayList) FileNotFoundException(java.io.FileNotFoundException) CorruptHFileException(org.apache.hadoop.hbase.io.hfile.CorruptHFileException) FileSystem(org.apache.hadoop.fs.FileSystem) Cell(org.apache.hadoop.hbase.Cell) ScannerContext(org.apache.hadoop.hbase.regionserver.ScannerContext) ShipperListener(org.apache.hadoop.hbase.regionserver.ShipperListener) CloseChecker(org.apache.hadoop.hbase.regionserver.compactions.CloseChecker) Path(org.apache.hadoop.fs.Path) KeyValueScanner(org.apache.hadoop.hbase.regionserver.KeyValueScanner) InterruptedIOException(java.io.InterruptedIOException) DoNotRetryIOException(org.apache.hadoop.hbase.DoNotRetryIOException) IOException(java.io.IOException) Date(java.util.Date) TableName(org.apache.hadoop.hbase.TableName)

Example 3 with CorruptHFileException

use of org.apache.hadoop.hbase.io.hfile.CorruptHFileException in project hbase by apache.

the class TestWALSplitToHFile method testCorruptRecoveredHFile.

@Test
public void testCorruptRecoveredHFile() throws Exception {
    Pair<TableDescriptor, RegionInfo> pair = setupTableAndRegion();
    TableDescriptor td = pair.getFirst();
    RegionInfo ri = pair.getSecond();
    WAL wal = createWAL(this.conf, rootDir, logName);
    HRegion region = HRegion.openHRegion(this.conf, this.fs, rootDir, ri, td, wal);
    writeData(td, region);
    // Now close the region without flush
    region.close(true);
    wal.shutdown();
    // split the log
    WALSplitter.split(rootDir, logDir, oldLogDir, FileSystem.get(this.conf), this.conf, wals);
    // Write a corrupt recovered hfile
    Path regionDir = new Path(CommonFSUtils.getTableDir(rootDir, td.getTableName()), ri.getEncodedName());
    for (ColumnFamilyDescriptor cfd : td.getColumnFamilies()) {
        FileStatus[] files = WALSplitUtil.getRecoveredHFiles(this.fs, regionDir, cfd.getNameAsString());
        assertNotNull(files);
        assertTrue(files.length > 0);
        writeCorruptRecoveredHFile(files[0].getPath());
    }
    // Failed to reopen the region
    WAL wal2 = createWAL(this.conf, rootDir, logName);
    try {
        HRegion.openHRegion(this.conf, this.fs, rootDir, ri, td, wal2);
        fail("Should fail to open region");
    } catch (CorruptHFileException che) {
    // Expected
    }
    // Set skip errors to true and reopen the region
    this.conf.setBoolean(HConstants.HREGION_EDITS_REPLAY_SKIP_ERRORS, true);
    HRegion region2 = HRegion.openHRegion(this.conf, this.fs, rootDir, ri, td, wal2);
    Result result2 = region2.get(new Get(ROW));
    assertEquals(td.getColumnFamilies().length, result2.size());
    for (ColumnFamilyDescriptor cfd : td.getColumnFamilies()) {
        assertTrue(Bytes.equals(VALUE1, result2.getValue(cfd.getName(), QUALIFIER)));
        // Assert the corrupt file was skipped and still exist
        FileStatus[] files = WALSplitUtil.getRecoveredHFiles(this.fs, regionDir, cfd.getNameAsString());
        assertNotNull(files);
        assertEquals(1, files.length);
        assertTrue(files[0].getPath().getName().contains("corrupt"));
    }
}
Also used : Path(org.apache.hadoop.fs.Path) HRegion(org.apache.hadoop.hbase.regionserver.HRegion) FileStatus(org.apache.hadoop.fs.FileStatus) Get(org.apache.hadoop.hbase.client.Get) RegionInfo(org.apache.hadoop.hbase.client.RegionInfo) CorruptHFileException(org.apache.hadoop.hbase.io.hfile.CorruptHFileException) ColumnFamilyDescriptor(org.apache.hadoop.hbase.client.ColumnFamilyDescriptor) TableDescriptor(org.apache.hadoop.hbase.client.TableDescriptor) Result(org.apache.hadoop.hbase.client.Result) Test(org.junit.Test)

Aggregations

Path (org.apache.hadoop.fs.Path)3 CorruptHFileException (org.apache.hadoop.hbase.io.hfile.CorruptHFileException)3 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 FileSystem (org.apache.hadoop.fs.FileSystem)2 DoNotRetryIOException (org.apache.hadoop.hbase.DoNotRetryIOException)2 InterruptedIOException (java.io.InterruptedIOException)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 FileStatus (org.apache.hadoop.fs.FileStatus)1 Cell (org.apache.hadoop.hbase.Cell)1 TableName (org.apache.hadoop.hbase.TableName)1 ColumnFamilyDescriptor (org.apache.hadoop.hbase.client.ColumnFamilyDescriptor)1 Get (org.apache.hadoop.hbase.client.Get)1 RegionInfo (org.apache.hadoop.hbase.client.RegionInfo)1 Result (org.apache.hadoop.hbase.client.Result)1 TableDescriptor (org.apache.hadoop.hbase.client.TableDescriptor)1 MobFile (org.apache.hadoop.hbase.mob.MobFile)1 HRegion (org.apache.hadoop.hbase.regionserver.HRegion)1 KeyValueScanner (org.apache.hadoop.hbase.regionserver.KeyValueScanner)1